Methods

Spatial data preparation

Load data

Maps data

We use three different shapefiles for the continental U.S. land mass, the State waters of maine, new hampshire, massachusets, connecticut, rhode island, new york, new jersey, delaware, maryland, virginia, north carolina and the North East EEZ.

1.- Land shapefile; covers the US land territory for visualization. Data provided from the map package.

2.- State waters; covers the state waters of the NE US states. Data from data.gov.

License: No license information was provided. If this work was prepared by an officer or employee of the United States government as part of that person’s official duties it is considered a U.S. Government Work.

3.- EEZ shapefile; Used the Sea Around Us shapefle updated to June 2016.

Create base shapefile for computation

As a first step we need to divide the NE US EEZ among the different states. For that we expanded state waters up to the 200 nautical miles to then estimate the percentage that each expanded-state-waters occupied. Note that in all cases these areas overlapped and percentages accounted for it. We did this by following these steps:

    1. Expand state waters using a buffer
    1. Grid that buffer on a 0.3 resolution
    1. Crop the buffer to the EEZ

1. Expand Spatial regions (a.k.a buffers)

We set a buffer of 410000 m (410 km, ~ 221 nm) that overshoots the EEZ a bit, but is eventually cropped

2. Expand grid within buffer

Here we expand a grid within the buffer so we can estimate the proportion of each state.

Note: Dark grey shaded area is the grid

2.1 Merge grid and buffers

Once we have a gridded area, we converted the grid to a sf so we can merge it with the buffered states and finally filter out everything outside the states polygon

3. Crop buffers to EEZ

Finally, we crop the grided buffers to within the EEZ to capture the actual water space.

Note: This step takes quite a while because of the size of the EEZ shapefile. No, you cannot use st_simplify() here

3.1 Paper figure; buffer plot
plot_data <-grid_eez_sf %>% 
    mutate(state = str_to_sentence(state)) %>% 
    left_join(state_lat)

p <- gridExtra::grid.arrange(
  # Overall (overlapping) position
  ggplot(plot_data) +
    geom_sf(data = eez_sf, aes(), fill = "white") + 
    geom_sf(aes(color = order, fill = order), alpha = 0.3) +
    geom_sf(data = land_sf, aes()) +
    geom_sf_label_repel(data = land_sf, aes(label= abrev), 
                      size = 2,
                      box.padding = 0.10,
                      hjust = 1) +
    scale_color_manual(values = state_pallet) +
    scale_fill_manual(values = state_pallet) +
    my_ggtheme_p(leg_pos = "",
                 ax_tx_s = 12) +
    coord_sf(ylim = c(30,48)) +
    scale_y_continuous(breaks = c(30,35,40,45))+
    labs(x = "", y = ""),
  # Showing each state separately
  
    ggplot(plot_data) +
    geom_sf(data = land_sf, aes(), fill = "grey80") +
    geom_sf( aes(color = order),size = 0.1, alpha = 0.8) +
    facet_wrap(~ state) +
    theme(legend.position = "top") +
    scale_color_manual(values = state_pallet,
                       labels = plot_data %>% arrange(order) %>%  pull(state) %>% unique()) +
    my_ggtheme_p(leg_pos = "",
                 ax_tx_s = 6,
                 axx_tx_ang = 45,
                 hjust = 1
                 ),
  nrow = 1,
  bottom = "Longitude",
  left = "Latitude")


  ggsave(filename = "buffer_figure.jpg",
         plot = p,
         path = my_path("R","Figures"),
         width = 10,
         height = 5
         )

Buffer figure for paper

Interpolation rutine

In this step we interpolate the survey data within the previously created grid following a Triangular Irregular Surface method.

  • We removed cases where wtcpue < 0

Functions needed

We need to create a couple of functions to run the whole process

Interpolation main fx (tis).

This is the main function used to interpolate the data per year. It follows a Triangular Irregular Surface method using the interp::interp() function. If you want to see the function clic on code


tis <- function(input_data, grid, yr, taxa, reg){
  
  # --------------- #
  # Testing
  # print(paste(yr))
  # yr = 1976
  # --------------- #
  
  # Filter data
  data <- input_data %>% 
    filter(year == yr,
           spp == taxa,
           region == reg
    ) %>% 
    # Average duplicated hauls in the same spot
    group_by(region,year,spp,lat,lon) %>%
    summarise_at(vars(wtcpue),
                 mean,na.rm = T)
    
  # Only interpolate cases where there is more than 3 rows
  # Marked by the function 
    if(nrow(data) <= 3){
      fit_tin <- tibble()
    }else{
      
      # Triangular Irregular Surface
      fit_tin <- interp::interp( # using {interp}
        x = data$lon,           # the function actually accepts coordinate vectors
        y = data$lat,
        z = data$wtcpue,
        xo = grid$lon,     # here we already define the target grid
        yo = grid$lat,
        output = "points"
      ) %>% 
        bind_cols() %>% 
        bind_cols(grid) %>%
        mutate(year = yr,
               region = reg,
               spp = taxa) %>% 
        select(index, state, year, region, spp, lon=x, lat=y, value = z)
      
    }
   
    return(fit_tin)
}

# Test me
# Needs variables in Control panel
# Test no data: "Alosa aestivalis", reg = "Northeast US Fall", yr = 1974 
# tis(input_data = ocean_data, grid = grid_eez_df, taxa = "Illex illecebrosus", reg = "Northeast US Fall", yr = 1973)



# lapply(years,tis,input_data = ocean_data, grid = grid_eez_df, taxa = "Illex illecebrosus", reg = regions[2])
Run function

This is a sub-function that runs the tis() function by taxa and region. It saves the output as a .csv file for each species.



run_tis <- function(input_data, grid, years, taxa, reg){
  
  
  # Run tis for species and surveys
  for(r in 1:2){
    
    partial_df <- bind_rows(
      lapply(years,tis,input_data = ocean_data, grid = grid_eez_df, taxa = taxa, reg = regions[r])
    )
    
    if(r == 1){
      historic_tif <- partial_df
    }else{
      historic_tif <- bind_rows(historic_tif,partial_df)
    }
    
  }
  
  # ----------------------- #
  # Save dataset per species
  # ----------------------- #
  
  # Set file name
  name <- paste0("tif_",str_replace(taxa," ","_"),".csv")
  
  # Set path name
  save_path <- my_path("R","Partial/Interpolation")
  
  # Set complete path
  save_name <- paste0(save_path,name)
  
  # Create folder if it does not exist
  if(file.exists(save_path) == F){
    dir.create(save_path)
  }
  
  #  Save file
  write_csv(historic_tif,save_name)
  
  return_msg <- paste("Interpolation done for", taxa)
  
  return(return_msg)
  
  
}

# Test me
    # run_tis(input_data = ocean_data, grid = grid_eez_df, taxa = "Centropristis striata", years = years, reg = regions)

Survey data

The interpolation was done with NOAA Northeast Fisheries Science Center Spring and Fall Bottom Trawl Surveys data provided by Ocean adapt. Data was accessed trough the Github.

In primary publications using data from the database, please cite Pinsky et al. 2013. Marine taxa track local climate velocities. Science 341: 1239-1242 doi: 10.1126/science.1239352, as well as the original data sources.

  • Using only the Northeast US Fall and Spring bottom trawl survey data for now
Splitting up data
  • No part on spatial analysis. Can be ignored.

This is just a sub-step to split up the data into single species files. This makes the app faster as it only needs to load species specific data, rather than all the data at de beginning.

Control Pannel

This is where we load the required data and prepare to run the interpolation function. Note that some of the data here has been previously created


# Load grid df
grid_eez_df <- my_path("D","Spatial","grid_eez_df.csv", read = T)

# Run interpolation for all years
years <- seq(1973,2019,1)

# regions
regions <- c("Northeast US Fall" , "Northeast US Spring")

# species list
spp <- ocean_data %>% 
  filter(region %in% regions,
         spp != "NA") %>% 
  pull(spp) %>% 
  unique()


# Double check runs

spp_runs <- tibble(taxa = (list.files(my_path("R","Partial/Interpolation")))) %>%
  mutate(
    taxa = str_remove(taxa, "tif_"),
    taxa = str_remove(taxa, ".csv"),
    taxa = str_replace(taxa, "_", " ")
  ) 

# Missing runs
spp <- tibble(taxa=spp) %>% 
  anti_join(spp_runs) %>% 
  pull(taxa)

Run routine

Here we just run the routine for each of the species present in the Northeast US Fall and Spring surveys between 1973 and 2019.

  • Note there are 43 identified taxa
  • Some taxa do not have presence data in some years

# single species run
# run_tis(input_data = ocean_data,
#         grid = grid_eez_df,
#         years = years,
#         reg = regions,
#         taxa = "Illex illecebrosus"
# )


# Run them all in parallel
lapply(spp,
                   run_tis, 
                   input_data = ocean_data,
                   grid = grid_eez_df,
                   years = years,
                   reg = regions
)

Results

Results are now for eight species managed under Mid-Atlantic Council Management Plans according to NOAA.

Scomber scombrus, Peprilus triacanthus (butterfish), Illex illecebrosus (shortfin squid), Paralichthys dentatus (summer flounder), Stenotomus chrysops (Scoop), Centropristis striata (black sea bass), Pomatomus saltatrix (Bluefish), Lopholatilus chamaeleonticeps (Golden tilefish), Caulolatilus microps (blueline tilefish) and Clupea harengus

unique(historic_spp$spp)
[1] "Centropristis striata" "Paralichthys dentatus" "Stenotomus chrysops"  

Average proportion

This map shows the aggregated extrapolated value from all three species per State average across the whole study period within each State’s water.

Note: This is intended to be a supplemental figure

Proportion Change

Here we show the average proportion of the interpolation by State and time period. Time periods were arbitrary defined as;

  • Early; 1973 to 1984
  • Mid; 1985 to 1997
  • Late; 1998 to 2011
  • Now; 2012 to 2019

Notes: Figure represents the Spring survey. This computation considers the Overlapping of state waters.

Dynamic figure: Aggregated Proportional change per survey

Paper figure; Per species maps

total_fited <- historic_spp %>% 
  group_by(year,region,spp) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")


state_fit <- historic_spp %>% 
  group_by(state,year,region,spp) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region","spp")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  left_join(periods,
            by = "year") %>% 
  group_by(state,order,label,region,spp) %>% 
  summarise(mean_per = round(mean(percentage)),.groups = "drop") %>% 
  #Only show results for spring
  filter(str_detect(region,"Spring")) %>% 
  mutate(spp = gsub(" ","\n",spp))

# The plot
map_plot <- land_sf %>% 
  left_join(state_fit,
            by = "state") %>% 
  ggplot() +
  geom_sf(aes(fill = mean_per)) +
  viridis::scale_fill_viridis("Average proportion per State", alpha = 0.8) +
  facet_grid(spp ~ label) +
  labs(x = "Longitude", 
       y = "Latitude") +
  my_ggtheme_p(facet_tx_s = 20,
               leg_pos = "bottom",
               axx_tx_ang = 45,
               ax_tx_s = 12,
               ax_tl_s = 18,
               hjust = 1) +
  theme(legend.key.width = unit(4,"line")) 


  ggsave(filename = "proportion_chg_spp.jpg",
         plot = map_plot,
         path = my_path("R","Figures"),
         width = 14,
         height = 14
         )

Proportion change per species map for paper

Paper figure: Aggregated Proportional change

Proportion change aggregated all species map for paper

Area plot

This graph shows the proportion of the interpolation value each State has over time.

Note: This plot is interactive. For ease comparison between States you can;

  • One click on any State to remove it from the plot
  • Two clicks on any State to isolate it from the plot (other states can then be added by just clicking on them).
  • The bottom panel allows you to reduce the time frame

Dynamic aggregated plot


total_fited <- historic_spp %>% 
  group_by(year,region) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")

# group by state
state_fit <- historic_spp %>% 
  group_by(state,year,region) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region")) %>%
  mutate(percentage = state_value/total_value*100)

# Plot me
p <- ggplot(state_fit) +
  geom_area(
    aes(
      x = year,
      y = round(percentage),
      fill = state
    )
  ) +
  ylab("Percentage (%)") +
  # viridis::scale_fill_viridis(discrete = T, alpha = 0.8) +
  scale_fill_manual(values = state_pallet) +
  MyFunctions::my_ggtheme_p() +
  facet_wrap(~region, ncol = 1) +
  theme_dark()

ggplotly(p,
         dynamicTicks = TRUE) %>% 
  layout(hovermode = "x") %>%
  rangeslider()
NA

Area plot (running mean)

This graph shows the proportion of each State smoothed over a *10 years running mean**. It allows to better see increasing and decreasing trends.

Dynamic aggregated plot

Note: This plot is also interactive and thus, follows the same options of the previous one.


# group by state
state_fit <- historic_spp %>% 
  group_by(state,year,region,.groups = "drop") %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  group_by(state,region) %>% 
  mutate(RMean = zoo::rollmean(x = percentage, 
                            10,
                            fill = NA,
                            na.rm=T)
    ) %>%  
  left_join(state_lat)
Joining, by = "state"
# Plot me
p <- ggplot(state_fit) +
  geom_area(
    aes(
      x = year,
      y = round(RMean),
      fill = state
      # fill = order
    )
  ) +
  ylab("10 yrs running average (%)") +
  scale_fill_manual(
    "State",
    values = state_pallet,
    # labels = state_fit %>% arrange(order) %>%  pull(state) %>% unique()
  ) +
  MyFunctions::my_ggtheme_p() +
  facet_wrap(~region, ncol = 1) +
  theme_dark()

suppressWarnings(
ggplotly(p,
         dynamicTicks = TRUE) %>% 
  layout(hovermode = "x") %>% 
  # add_trace() %>% 
  rangeslider()
)
NA

Paper figure: Aggregated Proportional change

Proportion change aggregated all species map for paper

Paper figure: Per Species Proportional change

Proportion change aggregated all species map for paper

Historic quota Vs distributions

This section of the results explores the differences between the historic distribution of te stock and the historic quota allocation. We collected the proportion of the total quota that each State gets for each species.

Right now the analysis only covers black sea bass, summer flounder and scup. But we can go speceis by species to see which ones have their quota allocated by state to include them in the analysis.

Note: We are using the new allocations based on the stock’s most recent biomass distribution*

For State-level managed species see the Atlantic States Marine Fisheries Comission website and go species-by-species.


quota_allocation <- state_lat %>% 
  mutate(
    "Centropristis striata" = c(
      0.0040, #ME
      0.0040, #NH
      0.1564, #MA
      0.1323, #RI
      0.0367, #CT
      0.0857, #NY
      0.2010, #NJ
      0.0411, #DE
      0.0888, #MD
      0.1614, #VA
      0.0888 #NC
    ),
    "Paralichthys dentatus" = c(
      0.0004756, #ME 
      0.0000046, #NH 
      0.0682046, #MA 
      0.1568298, #RI 
      0.0225708, #CT 
      0.0764699, #NY 
      0.1672499, #NJ 
      0.0001779, #DE 
      0.0203910, #MD
      0.2131676, #VA
      0.2744584 #NC
    ),
    "Stenotomus chrysops" = c(
      0.0012101, #ME
      0.0000000, #HN
      0.2158729, #MA
      0.5619456, #RI
      0.0315399, #CT
      0.1582466, #NY
      0.0291667, #NJ
      0.0000000, #DE
      0.0001190, #MD
      0.0016502, #VA
      0.0002490 #NC
    )
  ) %>% 
  gather("spp","quota",4:6)

# Double check they all add to 1...
quota_allocation %>% 
  group_by(spp) %>% 
  summarise_at(vars(quota),sum)


quota_allocation %>% 
  arrange(order) %>% 
  select(-order) %>% 
  spread(spp,quota) %>% 
  kable()
state abrev Centropristis striata Paralichthys dentatus Stenotomus chrysops
Connecticut CT 0.0367 0.0225708 0.0315399
Delaware DE 0.0411 0.0001779 0.0000000
Maine ME 0.0040 0.0004756 0.0012101
Maryland MD 0.0888 0.0203910 0.0001190
Massachusetts MA 0.1564 0.0682046 0.2158729
New hampshire NH 0.0040 0.0000046 0.0000000
New jersey NJ 0.2010 0.1672499 0.0291667
New york NY 0.0857 0.0764699 0.1582466
North carolina NC 0.0888 0.2744584 0.0002490
Rhode island RI 0.1323 0.1568298 0.5619456
Virginia VA 0.1614 0.2131676 0.0016502

Get data ready

state abrev year region spp quota state_value total_value Distribution Historic RMean order
Connecticut CT 1976 Northeast US Spring Centropristis striata 0.0367000 15.1325552 466.4871 3.2439387 3.67000 6.403059 e
Connecticut CT 1976 Northeast US Spring Paralichthys dentatus 0.0225708 82.6630292 712.1242 11.6079505 2.25708 11.297168 e
Connecticut CT 1976 Northeast US Spring Stenotomus chrysops 0.0315399 83.6256570 676.5664 12.3603025 3.15399 9.987846 e
Connecticut CT 1978 Northeast US Spring Centropristis striata 0.0367000 14.1686584 1262.1908 1.1225449 3.67000 6.056662 e
Connecticut CT 1978 Northeast US Spring Paralichthys dentatus 0.0225708 68.1083517 784.0304 8.6869531 2.25708 11.627109 e
Connecticut CT 1978 Northeast US Spring Stenotomus chrysops 0.0315399 0.4335304 2990.5258 0.0144968 3.15399 10.406455 e

Exploring different ways to show the results

Difference line plot

This version shows the difference between the Historic quota allocation and the distribution proportion of the stock:

  • diff < 0 = the distribution proportion is larger than the allocated quota
  • diff > 0 = the distribution proportion is smaller than the allocated quota

Linetype plot

Here, we plot the distributional quota (solid lines) with each State’s allocation with dashed (—-) lines

# Option one

quota_df %>% 
  gather("level","quota",Distribution:RMean) %>% 
  # mutate(diff = quota_per- percentage) %>% 
  # View()
  ggplot() +
  geom_line(
    aes(
      x = year,
      y = quota,
      color = order
    )
  ) +
  labs(x = "Year",y = "Quota (%)") +
  scale_fill_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  scale_color_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  scale_linetype("Quota") +
  facet_grid(spp ~ level)+
  theme_dark()

Efficiency index

The idea here is create and efficiency index (Danger!) that computes the alignment between the distribution and the actual allocation. The index is simply;

\[ei = \frac{HistoricQuota}{DistributionProportion}\] So, in cases where ei = 1, the quota is aligned with the distribution; when ei > 1 then the historic quota is more than the stock’s State’s distribution, contrarily, ei < 1 means that the historic quota is less than what the State currently has.

Note: - There are some crazzy outliers that have been removed, for now… - Bottom plot representing index as a Rmean

As a normal year to year

LS0tCnRpdGxlOiAiU3BhdGlhbCBBbmFseXNpcyIKYXV0aG9yOiAiSnVsaWFubyBQYWxhY2lvcyBBYnJhbnRlcyIKb3V0cHV0OgogICMgaHRtbF9kb2N1bWVudAogIGh0bWxfbm90ZWJvb2s6CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICB0aGVtZTogZGFya2x5Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoTXlGdW5jdGlvbnMpCk15RnVuY3Rpb25zOjpteV9saWIoYygiZ2dtYXAiLCJzZiIsInN0IiwidGlkeXZlcnNlIiwidG9vbHMiLCJyZWFkciIsImRhdGEudGFibGUiLCJtYXBzIiwidmlyaWRpcyIsIndlc2FuZGVyc29uIiwia25pdHIiLCJrYWJsZUV4dHJhIiwicGxvdGx5IiwiZ2dyZXBlbCIsImdnc2ZsYWJlbCIsImphbml0b3IiLCJpbnRlcnAiLCJybmF0dXJhbGVhcnRoIikpCmBgYAoKIyBNZXRob2RzCgojIyBTcGF0aWFsIGRhdGEgcHJlcGFyYXRpb24KCiMjIyBMb2FkIGRhdGEKCiMjIyMgTWFwcyBkYXRhCgpXZSB1c2UgdGhyZWUgZGlmZmVyZW50IHNoYXBlZmlsZXMgZm9yIHRoZSBjb250aW5lbnRhbCBVLlMuIGxhbmQgbWFzcywgdGhlIFN0YXRlIHdhdGVycyBvZiBtYWluZSwgbmV3IGhhbXBzaGlyZSwgbWFzc2FjaHVzZXRzLCBjb25uZWN0aWN1dCwgcmhvZGUgaXNsYW5kLCBuZXcgeW9yaywgbmV3IGplcnNleSwgZGVsYXdhcmUsIG1hcnlsYW5kLCB2aXJnaW5pYSwgbm9ydGggY2Fyb2xpbmEgYW5kIHRoZSBOb3J0aCBFYXN0IEVFWi4KCjEuLSAqKkxhbmQgc2hhcGVmaWxlOyoqIGNvdmVycyB0aGUgVVMgbGFuZCB0ZXJyaXRvcnkgZm9yIHZpc3VhbGl6YXRpb24uIERhdGEgcHJvdmlkZWQgZnJvbSB0aGUgYG1hcGAgcGFja2FnZS4KCjIuLSAqKlN0YXRlIHdhdGVyczsqKiBjb3ZlcnMgdGhlIHN0YXRlIHdhdGVycyBvZiB0aGUgTkUgVVMgc3RhdGVzLiBEYXRhIGZyb20gW2RhdGEuZ292XShodHRwczovL2NhdGFsb2cuZGF0YS5nb3YvZGF0YXNldC9mZWRlcmFsLWFuZC1zdGF0ZS13YXRlcnMpLiAgCgoqTGljZW5zZTogTm8gbGljZW5zZSBpbmZvcm1hdGlvbiB3YXMgcHJvdmlkZWQuIElmIHRoaXMgd29yayB3YXMgcHJlcGFyZWQgYnkgYW4gb2ZmaWNlciBvciBlbXBsb3llZSBvZiB0aGUgVW5pdGVkIFN0YXRlcyBnb3Zlcm5tZW50IGFzIHBhcnQgb2YgdGhhdCBwZXJzb24ncyBvZmZpY2lhbCBkdXRpZXMgaXQgaXMgY29uc2lkZXJlZCBhIFUuUy4gR292ZXJubWVudCBXb3JrLioKCjMuLSAqKkVFWiBzaGFwZWZpbGU7KiogVXNlZCB0aGUgKlNlYSBBcm91bmQgVXMqIHNoYXBlZmxlIHVwZGF0ZWQgdG8gSnVuZSAyMDE2LgoKYGBge3IgbWFwc19zZiwgZXZhbCA9IFQsIGVjaG8gPSBULCByZXN1bHRzID0gJ2hpZGUnfQoKU3RhdGVzIDwtIGMoIm1haW5lIiwgIm5ldyBoYW1wc2hpcmUiLCAibWFzc2FjaHVzZXR0cyIsICJjb25uZWN0aWN1dCIsICJyaG9kZSBpc2xhbmQiLCAibmV3IHlvcmsiLCAibmV3IGplcnNleSIsICJkZWxhd2FyZSIsICJtYXJ5bGFuZCIsICJ2aXJnaW5pYSIsICJub3J0aCBjYXJvbGluYSIpIAoKIyBVUyBTdGF0ZSBNYXAgKGxhbmQpCgpsYW5kX3NmIDwtIHN0X2FzX3NmKG1hcCgic3RhdGUiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSkgJT4lIAogIGZpbHRlcihJRCAlaW4lIFN0YXRlcykgJT4lIAogIG11dGF0ZShhYnJldiA9IGMoIkNPIiwiREUiLCJNRSIsIk1EIiwiTUEiLCJOSCIsIk5KIiwiTlkiLCJOQyIsIlJJIiwiVkkiKSkKCiMgZ2dwbG90KHVzX21hcCkgKwogICMgZ2VvbV9zZigpCgojIFVTIEVFWiBtYXAKCiMgcGF0aF93b3JsZCA8LSBteV9wYXRoKCJHIiwgZXh0cmFfcGF0aCA9ICJTcGF0aWFsL1NBVS9TQVVfU2hhcGVmaWxlIikKcGF0aF93b3JsZCA8LSAifi9PbmVEcml2ZSAtIFVXLU1hZGlzb24vU3BhdGlhbF9kYXRhL1dvcmxkX0VFWl92MTFfMjAxOTExMTgvIgoKIyBUaGUgRmlsZQpmbmFtX3dvcmxkIDwtICJlZXpfYm91bmRhcmllc192MTEuc2hwIgoKIyBMb2FkIGl0IQoKZWV6X3NmIDwtIHN0X3JlYWQoZHNuID0gcGF0aF93b3JsZCwKICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXIgPWZpbGVfcGF0aF9zYW5zX2V4dChmbmFtX3dvcmxkKSkgJT4lCiAgIyByZW5hbWUoZWV6X25hbWUgPSBOYW1lKSAlPiUKICAjIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgZmlsdGVyKFRFUlJJVE9SWTEgPT0gIlVuaXRlZCBTdGF0ZXMiLAogICAgICAgICBMRU5HVEhfS00gPT0gMjczNCkgIyU+JQogICMgZmlsdGVyKHN0cl9kZXRlY3QoRUVaMSwgIlVuaXRlZCBTdGF0ZXMiKSkgJT4lCiAgIyBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gVFJVRSwgZFRvbGVyYW5jZSA9IDAuMSkgIzAuMSBmb3IgcGFwZXIKCiMgZ2dwbG90KGVlel9zZikgKwogICMgZ2VvbV9zZigpCgoKIyBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKGRhdGEgPSBXb3JsZF9lZXpfc2YsIGFlcygpLCBjb2xvciA9ICJyZWQiKSArCiMgICBnZW9tX3NmKGRhdGEgPSB1c19tYXAsIGFlcygpLCBjb2xvciA9ICJibHVlIikKCiMgVVMgc3RhdGUgd2F0ZXJzCiMgaHR0cHM6Ly9jYXRhbG9nLmRhdGEuZ292L2RhdGFzZXQvZmVkZXJhbC1hbmQtc3RhdGUtd2F0ZXJzCgojIHVzX3N0YXRlX3cgPC0gcmdkYWw6OnJlYWRPR1IoZHNuID0gIn4vRG93bmxvYWRzL0ZlZGVyYWxBbmRTdGF0ZVdhdGVycy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikKc3RhdGVfc2YgPC0gIHN0X3JlYWQoIn4vT25lRHJpdmUgLSBVVy1NYWRpc29uL1NwYXRpYWxfRGF0YS9VU0ZlZEFuZFN0YXRlVy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikgJT4lCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgCiAgbXV0YXRlKGp1cmlzZGljdGkgPSBzdHJfdG9fbG93ZXIoanVyaXNkaWN0aSkpICU+JSAKICBmaWx0ZXIoanVyaXNkaWN0aSAlaW4lIFN0YXRlcykgJT4lIAogIHJlbmFtZShzdGF0ZSA9IGp1cmlzZGljdGkpICU+JSAKICAjIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAgIyBmb3IgbWF0Y2hpbmcgcHJvamVjdGlvbnMKICBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gVFJVRSwgZFRvbGVyYW5jZSA9IDEwMDAwKSAjMC4xIGZvciBwYXBlcgoKCmdyaWRfc2YgPC0gIHN0X3JlYWQoIi9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL0RhdGEvU3BhdGlhbC9ncmlkX3NmL2dyaWRfZWV6X3NmLnNocCIpCgoKIyBDcmVhdGUgc3BlY2lmaWMgc3RhdGUgcGFsbGV0IGZyb20gb3VyIGZyaWVuZCBXZXMgQW5kZXJzc29uCnN0YXRlX3BhbGxldCA8LSBjKHdlc19wYWxldHRlKG4gPSA1LCBuYW1lID0gIkRhcmplZWxpbmcxIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZXNfcGFsZXR0ZShuID0gNSwgbmFtZSA9ICJEYXJqZWVsaW5nMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VzX3BhbGV0dGUobiA9IDMsIG5hbWUgPSAiUm95YWwxIikKICAgICAgICAgICAgICAgICAgKQoKdW5pcXVlKGxhbmRfc2YkSUQpCgoKZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCkpICsKICBnZW9tX3NmKGRhdGEgPSBzdGF0ZV9zZiwgYWVzKGNvbG9yID0gc3RhdGUpLCBmaWxsID0gTkEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSsKICB0aGVtZV9kYXJrKCkKCmBgYAoKCiMjIyBDcmVhdGUgYmFzZSBzaGFwZWZpbGUgZm9yIGNvbXB1dGF0aW9uCgpBcyBhIGZpcnN0IHN0ZXAgd2UgbmVlZCB0byBkaXZpZGUgdGhlIE5FIFVTIEVFWiBhbW9uZyB0aGUgZGlmZmVyZW50IHN0YXRlcy4gRm9yIHRoYXQgd2UgZXhwYW5kZWQgc3RhdGUgd2F0ZXJzIHVwIHRvIHRoZSAyMDAgbmF1dGljYWwgbWlsZXMgdG8gdGhlbiBlc3RpbWF0ZSB0aGUgcGVyY2VudGFnZSB0aGF0IGVhY2ggZXhwYW5kZWQtc3RhdGUtd2F0ZXJzIG9jY3VwaWVkLiBOb3RlIHRoYXQgaW4gYWxsIGNhc2VzIHRoZXNlIGFyZWFzIG92ZXJsYXBwZWQgYW5kIHBlcmNlbnRhZ2VzIGFjY291bnRlZCBmb3IgaXQuIFdlIGRpZCB0aGlzIGJ5IGZvbGxvd2luZyB0aGVzZSBzdGVwczoKCi0gMS4gRXhwYW5kIHN0YXRlIHdhdGVycyB1c2luZyBhIGJ1ZmZlcgoKLSAyLiBHcmlkIHRoYXQgYnVmZmVyIG9uIGEgMC4zIHJlc29sdXRpb24KCi0gMy4gQ3JvcCB0aGUgYnVmZmVyIHRvIHRoZSBFRVoKCiMjIyMgMS4gRXhwYW5kIFNwYXRpYWwgcmVnaW9ucyAoYS5rLmEgIGJ1ZmZlcnMpCgpXZSBzZXQgYSBidWZmZXIgb2YgKjQxMDAwMCogbSAoNDEwIGttLCB+IDIyMSBubSkgdGhhdCBvdmVyc2hvb3RzIHRoZSBFRVogYSBiaXQsIGJ1dCBpcyBldmVudHVhbGx5IGNyb3BwZWQKCmBgYHtyIGJ1ZmZlciwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKIyBCdWZmZXIgc3RhdGUgd2F0ZXJzCnN0YXRlX2JmID0gc3RfYnVmZmVyKHN0YXRlX3NmLCA0MTAwMDApICU+JSAKICBzdF90cmFuc2Zvcm0oNDMyNikgJT4lICMgdG8gbWF0Y2ggc2hhcGUKICBzdF9zZXRfY3JzKDQzMjYpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCiMgVGVzdGluZyBhbmQgdmlzdWFsaXppbmcgdGhlIGJ1ZmZlciAKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwoKc3RhdGVfYmZfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gc3RhdGVfc2YsIGFlcyhjb2xvciA9IHN0YXRlKSwgZmlsbCA9IE5BKSArCiAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLCBhZXMoKSwgZmlsbCA9IE5BKSArCiAgZ2VvbV9zZihkYXRhID0gc3RhdGVfYmYsIGFlcyhjb2xvciA9IHN0YXRlKSwgZmlsbCA9IE5BKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkrCiAgdGhlbWVfZGFyaygpCiMgICAKCiMgZ2dzYXZlKCIuLi9SZXN1bHRzL1BhcnRpYWwvc3RhdGVfd2F0ZXJzX2J1ZmZlci5wbmciLHN0YXRlX2JmX3Bsb3QpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCgpzdGF0ZV9iZl9wbG90CgpgYGAKCiMjIyMgMi4gRXhwYW5kIGdyaWQgd2l0aGluIGJ1ZmZlcgoKSGVyZSB3ZSBleHBhbmQgYSBncmlkIHdpdGhpbiB0aGUgYnVmZmVyIHNvIHdlIGNhbiBlc3RpbWF0ZSB0aGUgcHJvcG9ydGlvbiBvZiBlYWNoIHN0YXRlLgoKKk5vdGU6KiBEYXJrIGdyZXkgc2hhZGVkIGFyZWEgaXMgdGhlIGdyaWQKCmBgYHtyIGdyaWRfaW5kZXhpbmcsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQoKIyBDcmVhdGUgZ3JpZCBvZiB0aGUgcmVnaW9uCmJib3ggPC0gYyhzdF9iYm94KHN0YXRlX2JmKSkKCiMgRXhwYW5kIHRoZSBncmlkCm5lX2dyaWQgPC0gZXhwYW5kLmdyaWQoCiAgICBsb24gPSBzZXEoZnJvbSA9IGJib3hbInhtaW4iXSwgdG8gPSBiYm94WyJ4bWF4Il0sIGJ5ID0gMC4zKSwKICAgIGxhdCA9IHNlcShmcm9tID0gYmJveFsieW1pbiJdLCB0byA9IGJib3hbInltYXgiXSwgYnkgPSAwLjMpCikgJT4lIAogIHJvd2lkX3RvX2NvbHVtbigiaW5kZXgiKQoKIyAtLS0tLS0tLS0tLSAjCiMgW1RFU1RdIFBsb3QgYWxsIGxheWVycwojIC0tLS0tLS0tLS0tICMKCiMgTG9va3MgZ29vZApzdGF0ZV9zZiAlPiUKICBzdF90cmFuc2Zvcm0oNDMyNikgJT4lICMgdG8gbWF0Y2ggc2hhcGUKICBzdF9zZXRfY3JzKDQzMjYpICU+JQogICMgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSAxMDAwMCkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGNvbG9yID0gc3RhdGUpKSsKICAjIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCksZmlsbCA9TkEpICsKICAjIGdncGxvdCgpKwogIGdlb21fdGlsZShkYXRhID0gbmVfZ3JpZCwKICAgICAgICAgICAgYWVzKAogICAgICAgICAgICAgIHggPSBsb24sCiAgICAgICAgICAgICAgeSA9IGxhdAogICAgICAgICAgICApLAogICAgICAgICAgICBhbHBoYSA9IDAuMgogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICB0aGVtZV9idygpKwogIHRoZW1lX2RhcmsoKQoKCmBgYAoKIyMjIyMgMi4xIE1lcmdlIGdyaWQgYW5kIGJ1ZmZlcnMKCk9uY2Ugd2UgaGF2ZSBhIGdyaWRkZWQgYXJlYSwgd2UgY29udmVydGVkIHRoZSBncmlkIHRvIGEgYHNmYCBzbyB3ZSBjYW4gbWVyZ2UgaXQgd2l0aCB0aGUgYnVmZmVyZWQgc3RhdGVzIGFuZCBmaW5hbGx5IGZpbHRlciBvdXQgZXZlcnl0aGluZyBvdXRzaWRlIHRoZSBzdGF0ZXMgcG9seWdvbgoKYGBge3IgZ3JpZF9idWZfbWVyZ2UsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBmaWcud2lkdGggPSAxMH0KCiMgLS0tLS0tLS0tLS0tLS0tLSAjCiMgQ29udmVydCBncmlkIHRvIHNmCiMgLS0tLS0tLS0tLS0tLS0tLSAjCmdyaWRfc2YgPC0gc3RfYXNfc2YobmVfZ3JpZCwKICAgICAgICAgICAgIGNvb3JkcyA9IGMoImxvbiIsICJsYXQiKSwKICAgICAgICAgICAgIGNycyA9IDQzMjYpICU+JSAKICBzdF9qb2luKHN0YXRlX2JmKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzdGF0ZSkpCgojIENyZWF0ZSBkYXRhIGZyYW1lIGZvciBmdXR1cmUgY29tcHV0YXRpb25zCiMgTm90ZSwgd2lsbCBiZSB1c2VkIGluIG5leHQgY2h1bmsKZ3JpZF9iZl9kdCA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfc2YpICU+JQogICAgc2VsZWN0KGluZGV4LHN0YXRlKQogICAgIyBncm91cF9ieShzdGF0ZSkgJT4lIAogICAgIyBzdW1tYXJpc2UobGVuZ3RoKGluZGV4KSkKCgojIC0tLS0tLS0tLS0tLS0tLS0gIwojIFtURVNUXSAKIyBWaXN1YWxpemF0aW9uIG9mIGdyaWQKIyAtLS0tLS0tLS0tLS0tLS0tICMKCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfc2YpICsKICAgIGdlb21fc2YoZGF0YSA9IHN0YXRlX3NmLCBhZXMoKSwgZmlsbCA9IE5BKSArCiAgICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSwgYWxwaGEgPSAwLjMpICsKICAgIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCksZmlsbCA9TkEpICsgCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICB0aGVtZV9kYXJrKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIiIpLAogICMgU2hvd2luZyBlYWNoIHN0YXRlIHNlcGFyYXRsZXkKICBnZ3Bsb3QoKSArCiAgICBnZW9tX3NmKGRhdGEgPSBncmlkX3NmLCBhZXMoY29sb3IgPSBzdGF0ZSksc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjUpICsKICAgIGZhY2V0X3dyYXAofnN0YXRlKSArCiAgICB0aGVtZV9kYXJrKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpLAogIG5yb3cgPSAxKSAKCmBgYAoKIyMjIyAzLiBDcm9wIGJ1ZmZlcnMgdG8gRUVaCgpGaW5hbGx5LCB3ZSBjcm9wIHRoZSBncmlkZWQgYnVmZmVycyB0byB3aXRoaW4gdGhlIEVFWiB0byBjYXB0dXJlIHRoZSBhY3R1YWwgd2F0ZXIgc3BhY2UuCgoqTm90ZToqIFRoaXMgc3RlcCB0YWtlcyBxdWl0ZSBhIHdoaWxlIGJlY2F1c2Ugb2YgdGhlIHNpemUgb2YgdGhlIEVFWiBzaGFwZWZpbGUuIE5vLCB5b3UgY2Fubm90IHVzZSBgc3Rfc2ltcGxpZnkoKWAgaGVyZQoKYGBge3IgYnVmZl90b19lZXosIGV2YWwgPVQsIGVjaG8gPSBULCBtZXNzYWdlID0gRiwgd2FybmluZyA9IEZ9CgojIEkgZG9uJ3Qga25vdyBob3cgdG8gdW5kbyBzdF9zaW1wbGlmeSBzbyBuZWVkIHRvIHJlLWxvYWQgdGhlIHNoYXBlZmlsZQoKZWV6X3NmIDwtIHN0X3JlYWQobXlfcGF0aCgiRyIsIGV4dHJhX3BhdGggPSAiU3BhdGlhbC9TQVUvU0FVX1NoYXBlZmlsZSIsIG5hbWUgPSAiU0FVRUVaX0p1bHkyMDE1LnNocCIpKSAlPiUgCiAgcmVuYW1lKGVlel9uYW1lID0gTmFtZSkgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgZmlsdGVyKGVlel9uYW1lID09ICJVU0EgKEVhc3QgQ29hc3QpIikgCgoKZWV6X3NmIDwtIHN0X3JlYWQoIi9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9TcGF0aWFsL1dvcmxkX0VFWl92MTFfMjAxOTExMTgvZWV6X3YxMS5zaHAiKSAlPiUKICAjIHJlbmFtZShlZXpfbmFtZSA9IE5hbWUpICU+JQogICMgc3RfdHJhbnNmb3JtKGNycyA9IDQzMjYpICU+JSAjIDQzMjYKICBmaWx0ZXIoVEVSUklUT1JZMSA9PSAiVW5pdGVkIFN0YXRlcyIpICU+JSAKICBzdF9jcm9wKHhtaW4gPSAtODUsIHhtYXggPSAtNjAsIHltaW4gPSAzMCwgeW1heCA9IDUwKQoKIyBnZ3Bsb3QoZWV6X3NmKSArCiMgICBnZW9tX3NmKCkKCiMgR2V0IHRoZSBvdmVybGFwcGluZyBzZWdtZW50cyAKIyBOT1RFOiBUYWtlcyBzb21lIGdvb29vb29kIHRpbWUKZ3JpZF9lZXpfc2YgPC0gc3RfaW50ZXJzZWN0aW9uKGdyaWRfc2YsZWV6X3NmKQoKIyB3cml0ZV9zZihncmlkX2Vlel9zZiwgcGFzdGUwKG15X3BhdGgoIkQiLCAiU3BhdGlhbCIpLCJncmlkX2Vlel9zZi5zaHAiKSkKCiMgR2V0IGZpbmFsIGRmIHdpdGggaW5kZXgKZ3JpZF9lZXpfZGYgPC0gYXMuZGF0YS5mcmFtZShncmlkX2Vlel9zZikgJT4lCiAgc2VsZWN0KHN0YXRlLGluZGV4KSAlPiUKICBsZWZ0X2pvaW4obmVfZ3JpZCwKICAgICAgICAgICAgYnkgPSAiaW5kZXgiKQoKIyB3cml0ZV9jc3YoZ3JpZF9lZXpfZGYsIHBhc3RlMChteV9wYXRoKCJSIiwgIlBhcnRpYWwiKSwiZ3JpZF9lZXpfZGYuY3N2IikpCgojIFBsb3QgdG8gbWFrZSBzdXJlIG1ha2VzIHNlbnNlCmdyaWRfZWV6X3NmICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSwgYWxwaGEgPSAwLjMpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLGFlcygpLCBmaWxsID0gTkEpICsKICB0aGVtZV9kYXJrKCkKCmBgYAoKIyMjIyMgMy4xIFBhcGVyIGZpZ3VyZTsgYnVmZmVyIHBsb3QKCmBgYHtyIGNyb3BwZWRfcGxvdF9wYXBlciwgZXZhbCA9IEYsIGVjaG8gPSBUfQoKCnBsb3RfZGF0YSA8LWdyaWRfZWV6X3NmICU+JSAKICAgIG11dGF0ZShzdGF0ZSA9IHN0cl90b19zZW50ZW5jZShzdGF0ZSkpICU+JSAKICAgIGxlZnRfam9pbihzdGF0ZV9sYXQpCgpwIDwtIGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KHBsb3RfZGF0YSkgKwogICAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLCBhZXMoKSwgZmlsbCA9ICJ3aGl0ZSIpICsgCiAgICBnZW9tX3NmKGFlcyhjb2xvciA9IG9yZGVyLCBmaWxsID0gb3JkZXIpLCBhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zZihkYXRhID0gbGFuZF9zZiwgYWVzKCkpICsKICAgIGdlb21fc2ZfbGFiZWxfcmVwZWwoZGF0YSA9IGxhbmRfc2YsIGFlcyhsYWJlbD0gYWJyZXYpLCAKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgICAgICAgICAgYm94LnBhZGRpbmcgPSAwLjEwLAogICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICAgIG15X2dndGhlbWVfcChsZWdfcG9zID0gIiIsCiAgICAgICAgICAgICAgICAgYXhfdHhfcyA9IDEyKSArCiAgICBjb29yZF9zZih5bGltID0gYygzMCw0OCkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDMwLDM1LDQwLDQ1KSkrCiAgICBsYWJzKHggPSAiIiwgeSA9ICIiKSwKICAjIFNob3dpbmcgZWFjaCBzdGF0ZSBzZXBhcmF0ZWx5CiAgCiAgICBnZ3Bsb3QocGxvdF9kYXRhKSArCiAgICBnZW9tX3NmKGRhdGEgPSBsYW5kX3NmLCBhZXMoKSwgZmlsbCA9ICJncmV5ODAiKSArCiAgICBnZW9tX3NmKCBhZXMoY29sb3IgPSBvcmRlciksc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjgpICsKICAgIGZhY2V0X3dyYXAofiBzdGF0ZSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gcGxvdF9kYXRhICU+JSBhcnJhbmdlKG9yZGVyKSAlPiUgIHB1bGwoc3RhdGUpICU+JSB1bmlxdWUoKSkgKwogICAgbXlfZ2d0aGVtZV9wKGxlZ19wb3MgPSAiIiwKICAgICAgICAgICAgICAgICBheF90eF9zID0gNiwKICAgICAgICAgICAgICAgICBheHhfdHhfYW5nID0gNDUsCiAgICAgICAgICAgICAgICAgaGp1c3QgPSAxCiAgICAgICAgICAgICAgICAgKSwKICBucm93ID0gMSwKICBib3R0b20gPSAiTG9uZ2l0dWRlIiwKICBsZWZ0ID0gIkxhdGl0dWRlIikKCgogIGdnc2F2ZShmaWxlbmFtZSA9ICJidWZmZXJfZmlndXJlLmpwZyIsCiAgICAgICAgIHBsb3QgPSBwLAogICAgICAgICBwYXRoID0gbXlfcGF0aCgiUiIsIkZpZ3VyZXMiKSwKICAgICAgICAgd2lkdGggPSAxMCwKICAgICAgICAgaGVpZ2h0ID0gNQogICAgICAgICApCgpgYGAKCiFbQnVmZmVyIGZpZ3VyZSBmb3IgcGFwZXJdKC9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL1Jlc3VsdHMvRmlndXJlcy9idWZmZXJfZmlndXJlLmpwZykKCgoKCmBgYHtyIHJlbW92ZV9wZW4sIGV2YWwgPSBGLCBlY2hvID0gRn0KCiMjIyNfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXyMjIyAKIyBTb2x2aW5nIGZvciBJc3N1ZSAjOCBQZW5uc3lsdmFuaWEgaGFzIE5PIGNvYXN0CiMjIyNfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXyMjIyAKCiMgUmVtb3ZlIFBlbm5zeWx2YW5pYSBmcm9tIHNmCmdyaWRfZWV6X3NmIDwtICBzdF9yZWFkKCIvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9EYXRhL1NwYXRpYWwvZ3JpZF9zZi9ncmlkX2Vlel9zZi5zaHAiKSAlPiUKICBmaWx0ZXIoc3RhdGUgIT0gInBlbm5zeWx2YW5pYSIpCgojIE1ha2Ugc3VyZSBubyBQZW5uLgp1bmlxdWUoZ3JpZF9lZXpfc2Ykc3RhdGUpCgojIG92ZXIgd3JpdGUgc2YKd3JpdGVfc2YoZ3JpZF9lZXpfc2YsIHBhc3RlMChteV9wYXRoKCJEIiwgIlNwYXRpYWwiKSwiZ3JpZF9lZXpfc2Yuc2hwIikpCgojTWFrZSBzdXJlIG9mIHRoaW5ncwoKIyBncmlkX2Vlel9zZiA8LSAgc3RfcmVhZCgiL1ZvbHVtZXMvRW50ZXJwcmlzZS9EYXRhL0Fjcm9zc0JvdW5kYXJpZXMvRGF0YS9TcGF0aWFsL2dyaWRfc2YvZ3JpZF9lZXpfc2Yuc2hwIikKCiMgdW5pcXVlKGdyaWRfZWV6X3NmJHN0YXRlKQoKIyBOb3cgc2F2ZSBpdCBhcyBhIERGIHRvbwoKIyBncmlkX2Vlel9kZiA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfZWV6X3NmKSAlPiUKICAjIHNlbGVjdChzdGF0ZSxpbmRleCkgJT4lCiAgIyBsZWZ0X2pvaW4obmVfZ3JpZCwKICAgICAgICAgICAgIyBieSA9ICJpbmRleCIpCgojIHdyaXRlX2NzdihncmlkX2Vlel9kZiwgcGFzdGUwKG15X3BhdGgoIlIiLCAiUGFydGlhbCIpLCJncmlkX2Vlel9kZi5jc3YiKSkKYGBgCgoKIyMjIEludGVycG9sYXRpb24gcnV0aW5lCgpJbiB0aGlzIHN0ZXAgd2UgW2ludGVycG9sYXRlXShodHRwczovL3N3aWxrZS1nZW9zY2llbmNlLm5ldC9wb3N0L3NwYXRpYWxfaW50ZXJwb2xhdGlvbi8pIHRoZSBzdXJ2ZXkgZGF0YSB3aXRoaW4gdGhlIHByZXZpb3VzbHkgY3JlYXRlZCBncmlkIGZvbGxvd2luZyBhIFRyaWFuZ3VsYXIgSXJyZWd1bGFyIFN1cmZhY2UgbWV0aG9kLgoKLSBXZSByZW1vdmVkIGNhc2VzIHdoZXJlIGB3dGNwdWUgPCAwYAoKIyMjIyBGdW5jdGlvbnMgbmVlZGVkCgpXZSBuZWVkIHRvIGNyZWF0ZSBhIGNvdXBsZSBvZiBmdW5jdGlvbnMgdG8gcnVuIHRoZSB3aG9sZSBwcm9jZXNzCgojIyMjIyBJbnRlcnBvbGF0aW9uIG1haW4gZnggKHRpcykuCgpUaGlzIGlzIHRoZSBtYWluIGZ1bmN0aW9uIHVzZWQgdG8gaW50ZXJwb2xhdGUgdGhlIGRhdGEgcGVyIHllYXIuIEl0IGZvbGxvd3MgYSBUcmlhbmd1bGFyIElycmVndWxhciBTdXJmYWNlIG1ldGhvZCB1c2luZyB0aGUgYGludGVycDo6aW50ZXJwKClgIGZ1bmN0aW9uLiBJZiB5b3Ugd2FudCB0byBzZWUgdGhlIGZ1bmN0aW9uIGNsaWMgb24gYGNvZGVgCgpgYGB7ciBpbnRlcnBvbF9mdW5jdGlvbiwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKdGlzIDwtIGZ1bmN0aW9uKGlucHV0X2RhdGEsIGdyaWQsIHlyLCB0YXhhLCByZWcpewogIAogICMgLS0tLS0tLS0tLS0tLS0tICMKICAjIFRlc3RpbmcKICAjIHByaW50KHBhc3RlKHlyKSkKICAjIHlyID0gMTk3NgogICMgLS0tLS0tLS0tLS0tLS0tICMKICAKICAjIEZpbHRlciBkYXRhCiAgZGF0YSA8LSBpbnB1dF9kYXRhICU+JSAKICAgIGZpbHRlcih5ZWFyID09IHlyLAogICAgICAgICAgIHNwcCA9PSB0YXhhLAogICAgICAgICAgIHJlZ2lvbiA9PSByZWcKICAgICkgJT4lIAogICAgIyBBdmVyYWdlIGR1cGxpY2F0ZWQgaGF1bHMgaW4gdGhlIHNhbWUgc3BvdAogICAgZ3JvdXBfYnkocmVnaW9uLHllYXIsc3BwLGxhdCxsb24pICU+JQogICAgc3VtbWFyaXNlX2F0KHZhcnMod3RjcHVlKSwKICAgICAgICAgICAgICAgICBtZWFuLG5hLnJtID0gVCkKICAgIAogICMgT25seSBpbnRlcnBvbGF0ZSBjYXNlcyB3aGVyZSB0aGVyZSBpcyBtb3JlIHRoYW4gMyByb3dzCiAgIyBNYXJrZWQgYnkgdGhlIGZ1bmN0aW9uIAogICAgaWYobnJvdyhkYXRhKSA8PSAzKXsKICAgICAgZml0X3RpbiA8LSB0aWJibGUoKQogICAgfWVsc2V7CiAgICAgIAogICAgICAjIFRyaWFuZ3VsYXIgSXJyZWd1bGFyIFN1cmZhY2UKICAgICAgZml0X3RpbiA8LSBpbnRlcnA6OmludGVycCggIyB1c2luZyB7aW50ZXJwfQogICAgICAgIHggPSBkYXRhJGxvbiwgICAgICAgICAgICMgdGhlIGZ1bmN0aW9uIGFjdHVhbGx5IGFjY2VwdHMgY29vcmRpbmF0ZSB2ZWN0b3JzCiAgICAgICAgeSA9IGRhdGEkbGF0LAogICAgICAgIHogPSBkYXRhJHd0Y3B1ZSwKICAgICAgICB4byA9IGdyaWQkbG9uLCAgICAgIyBoZXJlIHdlIGFscmVhZHkgZGVmaW5lIHRoZSB0YXJnZXQgZ3JpZAogICAgICAgIHlvID0gZ3JpZCRsYXQsCiAgICAgICAgb3V0cHV0ID0gInBvaW50cyIKICAgICAgKSAlPiUgCiAgICAgICAgYmluZF9jb2xzKCkgJT4lIAogICAgICAgIGJpbmRfY29scyhncmlkKSAlPiUKICAgICAgICBtdXRhdGUoeWVhciA9IHlyLAogICAgICAgICAgICAgICByZWdpb24gPSByZWcsCiAgICAgICAgICAgICAgIHNwcCA9IHRheGEpICU+JSAKICAgICAgICBzZWxlY3QoaW5kZXgsIHN0YXRlLCB5ZWFyLCByZWdpb24sIHNwcCwgbG9uPXgsIGxhdD15LCB2YWx1ZSA9IHopCiAgICAgIAogICAgfQogICAKICAgIHJldHVybihmaXRfdGluKQp9CgojIFRlc3QgbWUKIyBOZWVkcyB2YXJpYWJsZXMgaW4gQ29udHJvbCBwYW5lbAojIFRlc3Qgbm8gZGF0YTogIkFsb3NhIGFlc3RpdmFsaXMiLCByZWcgPSAiTm9ydGhlYXN0IFVTIEZhbGwiLCB5ciA9IDE5NzQgCiMgdGlzKGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLCBncmlkID0gZ3JpZF9lZXpfZGYsIHRheGEgPSAiSWxsZXggaWxsZWNlYnJvc3VzIiwgcmVnID0gIk5vcnRoZWFzdCBVUyBGYWxsIiwgeXIgPSAxOTczKQoKCgojIGxhcHBseSh5ZWFycyx0aXMsaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsIGdyaWQgPSBncmlkX2Vlel9kZiwgdGF4YSA9ICJJbGxleCBpbGxlY2Vicm9zdXMiLCByZWcgPSByZWdpb25zWzJdKQoKYGBgCgojIyMjIyBSdW4gZnVuY3Rpb24KClRoaXMgaXMgYSBzdWItZnVuY3Rpb24gdGhhdCBydW5zIHRoZSBgdGlzKClgIGZ1bmN0aW9uIGJ5IHRheGEgYW5kIHJlZ2lvbi4gSXQgc2F2ZXMgdGhlIG91dHB1dCBhcyBhIC5jc3YgZmlsZSBmb3IgZWFjaCBzcGVjaWVzLiAKCmBgYHtyIGludGVycG9sX3J1bl9mdW4sIGV2YWwgPSBULCBlY2hvID0gVH0KCgpydW5fdGlzIDwtIGZ1bmN0aW9uKGlucHV0X2RhdGEsIGdyaWQsIHllYXJzLCB0YXhhLCByZWcpewogIAogIAogICMgUnVuIHRpcyBmb3Igc3BlY2llcyBhbmQgc3VydmV5cwogIGZvcihyIGluIDE6Mil7CiAgICAKICAgIHBhcnRpYWxfZGYgPC0gYmluZF9yb3dzKAogICAgICBsYXBwbHkoeWVhcnMsdGlzLGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLCBncmlkID0gZ3JpZF9lZXpfZGYsIHRheGEgPSB0YXhhLCByZWcgPSByZWdpb25zW3JdKQogICAgKQogICAgCiAgICBpZihyID09IDEpewogICAgICBoaXN0b3JpY190aWYgPC0gcGFydGlhbF9kZgogICAgfWVsc2V7CiAgICAgIGhpc3RvcmljX3RpZiA8LSBiaW5kX3Jvd3MoaGlzdG9yaWNfdGlmLHBhcnRpYWxfZGYpCiAgICB9CiAgICAKICB9CiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCiAgIyBTYXZlIGRhdGFzZXQgcGVyIHNwZWNpZXMKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKICAKICAjIFNldCBmaWxlIG5hbWUKICBuYW1lIDwtIHBhc3RlMCgidGlmXyIsc3RyX3JlcGxhY2UodGF4YSwiICIsIl8iKSwiLmNzdiIpCiAgCiAgIyBTZXQgcGF0aCBuYW1lCiAgc2F2ZV9wYXRoIDwtIG15X3BhdGgoIlIiLCJQYXJ0aWFsL0ludGVycG9sYXRpb24iKQogIAogICMgU2V0IGNvbXBsZXRlIHBhdGgKICBzYXZlX25hbWUgPC0gcGFzdGUwKHNhdmVfcGF0aCxuYW1lKQogIAogICMgQ3JlYXRlIGZvbGRlciBpZiBpdCBkb2VzIG5vdCBleGlzdAogIGlmKGZpbGUuZXhpc3RzKHNhdmVfcGF0aCkgPT0gRil7CiAgICBkaXIuY3JlYXRlKHNhdmVfcGF0aCkKICB9CiAgCiAgIyAgU2F2ZSBmaWxlCiAgd3JpdGVfY3N2KGhpc3RvcmljX3RpZixzYXZlX25hbWUpCiAgCiAgcmV0dXJuX21zZyA8LSBwYXN0ZSgiSW50ZXJwb2xhdGlvbiBkb25lIGZvciIsIHRheGEpCiAgCiAgcmV0dXJuKHJldHVybl9tc2cpCiAgCiAgCn0KCiMgVGVzdCBtZQogICAgIyBydW5fdGlzKGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLCBncmlkID0gZ3JpZF9lZXpfZGYsIHRheGEgPSAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiwgeWVhcnMgPSB5ZWFycywgcmVnID0gcmVnaW9ucykKCmBgYAoKCiMjIyMgU3VydmV5IGRhdGEKClRoZSBpbnRlcnBvbGF0aW9uIHdhcyBkb25lIHdpdGggTk9BQSBOb3J0aGVhc3QgRmlzaGVyaWVzIFNjaWVuY2UgQ2VudGVyIFNwcmluZyBhbmQgRmFsbCBCb3R0b20gVHJhd2wgU3VydmV5cyBbZGF0YV0oaHR0cHM6Ly93d3cuZmlzaGVyaWVzLm5vYWEuZ292L3JlZ2lvbi9uZXctZW5nbGFuZC1taWQtYXRsYW50aWMjc2NpZW5jZSkgcHJvdmlkZWQgYnkgW09jZWFuIGFkYXB0XShodHRwczovL29jZWFuYWRhcHQucnV0Z2Vycy5lZHUvKS4gRGF0YSB3YXMgYWNjZXNzZWQgdHJvdWdoIHRoZSBbR2l0aHViXShodHRwczovL2dpdGh1Yi5jb20vcGluc2t5bGFiL09jZWFuQWRhcHQpLgoKKkluIHByaW1hcnkgcHVibGljYXRpb25zIHVzaW5nIGRhdGEgZnJvbSB0aGUgZGF0YWJhc2UsIHBsZWFzZSBjaXRlIFBpbnNreSBldCBhbC4gMjAxMy4gTWFyaW5lIHRheGEgdHJhY2sgbG9jYWwgY2xpbWF0ZSB2ZWxvY2l0aWVzLiBTY2llbmNlIDM0MTogMTIzOS0xMjQyIGRvaTogMTAuMTEyNi9zY2llbmNlLjEyMzkzNTIsIGFzIHdlbGwgYXMgdGhlIG9yaWdpbmFsIGRhdGEgc291cmNlcy4qCgotIFVzaW5nIG9ubHkgdGhlIE5vcnRoZWFzdCBVUyBGYWxsIGFuZCBTcHJpbmcgYm90dG9tIHRyYXdsIHN1cnZleSBkYXRhIGZvciBub3cKCiMjIyMjIFNwbGl0dGluZyB1cCBkYXRhCgotIE5vIHBhcnQgb24gc3BhdGlhbCBhbmFseXNpcy4gQ2FuIGJlIGlnbm9yZWQuIAoKVGhpcyBpcyBqdXN0IGEgc3ViLXN0ZXAgdG8gc3BsaXQgdXAgdGhlIGRhdGEgaW50byBzaW5nbGUgc3BlY2llcyBmaWxlcy4gVGhpcyBtYWtlcyB0aGUgYXBwIGZhc3RlciBhcyBpdCBvbmx5IG5lZWRzIHRvIGxvYWQgc3BlY2llcyBzcGVjaWZpYyBkYXRhLCByYXRoZXIgdGhhbiBhbGwgdGhlIGRhdGEgYXQgZGUgYmVnaW5uaW5nLiAKCmBgYHtyIGRhdF9leHBsb2RlZCwgZXZhbCA9IEYsIGVjaG8gPSBGLCBmaWcud2lkdGggPSA5fQoKb2NlYW5fZGF0YSA8LSByZWFkUkRTKCIvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvcGluc2t5bGFiLU9jZWFuQWRhcHQtOTY2YWRmMC9kYXRhX2NsZWFuL2RhdF9leHBsb2RlZC5yZHMiKSAjJT4lIAogICMgZmlsdGVyKHNwcCA9PSAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiwKICAgICAgICMgcmVnaW9uICVpbiUgYygiTm9ydGhlYXN0IFVTIEZhbGwiICwgIk5vcnRoZWFzdCBVUyBTcHJpbmciKSkgI05vIG1vcmUgc2Vhc29ucwoKCnNwcF9kYXRhIDwtIGZ1bmN0aW9uKHNwcCl7CiAgCiAgbmFtZV9zYXZlIDwtIHBhc3RlMChteV9wYXRoKCJEIiwiU3BwL09ic2VydmF0aW9uIiksIm9ic18iLHN0cl9yZXBsYWNlKHNwcFsxXSwgIiAiLCAiXyIpLCIuY3N2IikKCm9jZWFuX2RhdGEgJT4lIAogIGZpbHRlcihzcHAgPT0gc3BwLAogICAgICAgcmVnaW9uICVpbiUgYygiTm9ydGhlYXN0IFVTIEZhbGwiICwgIk5vcnRoZWFzdCBVUyBTcHJpbmciKQogICAgICAgKSAlPiUgCiAgd3JpdGVfY3N2KC4sIG5hbWVfc2F2ZSkKICAKfQoKc3BwX2xpc3QgPC0gb2NlYW5fZGF0YSAlPiUgCiAgZmlsdGVyKHJlZ2lvbiAlaW4lIHJlZ2lvbnMsCiAgICAgICAgIHNwcCAhPSAiTkEiKSAlPiUgCiAgcHVsbChzcHApICU+JSAKICB1bmlxdWUoKQogIAoKbGFwcGx5KHNwcF9saXN0LCBzcHBfZGF0YSkKCgpzdWJzZXRfZGF0YSA8LSBvY2Vhbl9kYXRhICU+JSAKICBmaWx0ZXIoc3BwID09ICJDZW50cm9wcmlzdGlzIHN0cmlhdGEiLAogICAgICAgcmVnaW9uICVpbiUgYygiTm9ydGhlYXN0IFVTIEZhbGwiICwgIk5vcnRoZWFzdCBVUyBTcHJpbmciKQogICAgICAgKQoKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHN1YnNldChzdWJzZXRfZGF0YSwgd3RjcHVlID0gMC4wKSwKICAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICAgeCA9IGxvbiwKICAgICAgICAgICAgICAgeSA9IGxhdAogICAgICAgICAgICAgKSwKICAgICAgICAgICAgIGNvbG9yID0gImdyZXk5NSIKICApICsKICBnZW9tX3BvaW50KGRhdGEgPSBzdWJzZXQoc3Vic2V0X2RhdGEsIHd0Y3B1ZSA+IDApLAogICAgICAgICAgICAgYWVzKAogICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgICB5ID0gbGF0LAogICAgICAgICAgICAgICBjb2xvciA9IGxvZzEwKHd0Y3B1ZSkKICAgICAgICAgICAgICksCiAgICAgICAgICAgICBzaXplID0gMQogICkgKwogIHNjYWxlX2NvbG9yX2Rpc3RpbGxlcihwYWxldHRlID0gIlNwZWN0cmFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJXQ1BVRSBwZXIgSGF1bCAobG9nMTApIikpICsgCiAgY29vcmRfc2YoeGxpbSA9IGMoLTc2LCAtNjUpLHlsaW0gPSBjKDM1LCA0NSkpICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9tKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbikKCmBgYAoKIyMjIyBDb250cm9sIFBhbm5lbAoKVGhpcyBpcyB3aGVyZSB3ZSBsb2FkIHRoZSByZXF1aXJlZCBkYXRhIGFuZCBwcmVwYXJlIHRvIHJ1biB0aGUgaW50ZXJwb2xhdGlvbiBmdW5jdGlvbi4gTm90ZSB0aGF0IHNvbWUgb2YgdGhlIGRhdGEgaGVyZSBoYXMgYmVlbiBwcmV2aW91c2x5IGNyZWF0ZWQgCgpgYGB7ciBjb250cm9fcGFubmVsLCBldmFsID0gVCwgZWNobyA9IFR9CgojIExvYWQgZ3JpZCBkZgpncmlkX2Vlel9kZiA8LSBteV9wYXRoKCJEIiwiU3BhdGlhbCIsImdyaWRfZWV6X2RmLmNzdiIsIHJlYWQgPSBUKQoKIyBSdW4gaW50ZXJwb2xhdGlvbiBmb3IgYWxsIHllYXJzCnllYXJzIDwtIHNlcSgxOTczLDIwMTksMSkKCiMgcmVnaW9ucwpyZWdpb25zIDwtIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikKCiMgc3BlY2llcyBsaXN0CnNwcCA8LSBvY2Vhbl9kYXRhICU+JSAKICBmaWx0ZXIocmVnaW9uICVpbiUgcmVnaW9ucywKICAgICAgICAgc3BwICE9ICJOQSIpICU+JSAKICBwdWxsKHNwcCkgJT4lIAogIHVuaXF1ZSgpCgoKIyBEb3VibGUgY2hlY2sgcnVucwoKc3BwX3J1bnMgPC0gdGliYmxlKHRheGEgPSAobGlzdC5maWxlcyhteV9wYXRoKCJSIiwiUGFydGlhbC9JbnRlcnBvbGF0aW9uIikpKSkgJT4lCiAgbXV0YXRlKAogICAgdGF4YSA9IHN0cl9yZW1vdmUodGF4YSwgInRpZl8iKSwKICAgIHRheGEgPSBzdHJfcmVtb3ZlKHRheGEsICIuY3N2IiksCiAgICB0YXhhID0gc3RyX3JlcGxhY2UodGF4YSwgIl8iLCAiICIpCiAgKSAKCiMgTWlzc2luZyBydW5zCnNwcCA8LSB0aWJibGUodGF4YT1zcHApICU+JSAKICBhbnRpX2pvaW4oc3BwX3J1bnMpICU+JSAKICBwdWxsKHRheGEpCgoKYGBgCgojIyMjIFJ1biByb3V0aW5lCgpIZXJlIHdlIGp1c3QgcnVuIHRoZSByb3V0aW5lIGZvciBlYWNoIG9mIHRoZSBzcGVjaWVzIHByZXNlbnQgaW4gdGhlIE5vcnRoZWFzdCBVUyBGYWxsIGFuZCBTcHJpbmcgc3VydmV5cyBiZXR3ZWVuIDE5NzMgYW5kIDIwMTkuIAoKLSBOb3RlIHRoZXJlIGFyZSA0MyBpZGVudGlmaWVkIHRheGEKLSBTb21lIHRheGEgZG8gbm90IGhhdmUgcHJlc2VuY2UgZGF0YSBpbiBzb21lIHllYXJzCgpgYGB7ciBydW5fcm91dGluZSwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKIyBzaW5nbGUgc3BlY2llcyBydW4KIyBydW5fdGlzKGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLAojICAgICAgICAgZ3JpZCA9IGdyaWRfZWV6X2RmLAojICAgICAgICAgeWVhcnMgPSB5ZWFycywKIyAgICAgICAgIHJlZyA9IHJlZ2lvbnMsCiMgICAgICAgICB0YXhhID0gIklsbGV4IGlsbGVjZWJyb3N1cyIKIyApCgoKIyBSdW4gdGhlbSBhbGwgaW4gcGFyYWxsZWwKbGFwcGx5KHNwcCwKICAgICAgICAgICAgICAgICAgIHJ1bl90aXMsIAogICAgICAgICAgICAgICAgICAgaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsCiAgICAgICAgICAgICAgICAgICBncmlkID0gZ3JpZF9lZXpfZGYsCiAgICAgICAgICAgICAgICAgICB5ZWFycyA9IHllYXJzLAogICAgICAgICAgICAgICAgICAgcmVnID0gcmVnaW9ucwopCgoKYGBgCgojIFJlc3VsdHMKClJlc3VsdHMgYXJlIG5vdyBmb3IgZWlnaHQgc3BlY2llcyBtYW5hZ2VkIHVuZGVyIE1pZC1BdGxhbnRpYyBDb3VuY2lsIE1hbmFnZW1lbnQgUGxhbnMgYWNjb3JkaW5nIHRvIFtOT0FBXShodHRwczovL3d3dy5maXNoZXJpZXMubm9hYS5nb3YvbmV3LWVuZ2xhbmQtbWlkLWF0bGFudGljL2NvbW1lcmNpYWwtZmlzaGluZy9uZXctZW5nbGFuZC1taWQtYXRsYW50aWMtZmlzaGVyeS1tYW5hZ2VtZW50LXBsYW5zKS4KCgoqU2NvbWJlciBzY29tYnJ1cyosICpQZXByaWx1cyB0cmlhY2FudGh1cyogKGJ1dHRlcmZpc2gpLCAqSWxsZXggaWxsZWNlYnJvc3VzKiAoc2hvcnRmaW4gc3F1aWQpLCAqUGFyYWxpY2h0aHlzIGRlbnRhdHVzKiAoc3VtbWVyIGZsb3VuZGVyKSwgKlN0ZW5vdG9tdXMgY2hyeXNvcHMqIChTY29vcCksICpDZW50cm9wcmlzdGlzIHN0cmlhdGEqIChibGFjayBzZWEgYmFzcyksICpQb21hdG9tdXMgc2FsdGF0cml4KiAoQmx1ZWZpc2gpLCAqTG9waG9sYXRpbHVzIGNoYW1hZWxlb250aWNlcHMqIChHb2xkZW4gdGlsZWZpc2gpLCAqQ2F1bG9sYXRpbHVzIG1pY3JvcHMqIChibHVlbGluZSB0aWxlZmlzaCkgYW5kICpDbHVwZWEgaGFyZW5ndXMqCgoKYGBge3IgbG9hZF9kYXRhLCBldmFsID0gVCwgZWNobyA9IFR9CgojIFNwZWNpZXMgZGF0YQoKIyBMb2FkIGludGVycG9sYXRlZCBkYXRhCiMgIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIKIyAKIyBoaXN0b3JpY190aWYgPC0gbXlfcGF0aCgiUiIsIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIsInRpZl9DZW50cm9wcmlzdGlzX3N0cmlhdGEuY3N2IiwgcmVhZCA9IFQpICU+JSAKIyAgIG11dGF0ZShzdGF0ZSA9IHN0cl90b19zZW50ZW5jZShzdGF0ZSkpCgoKIyBNdWx0aXBsZSBzcGVjaWVzCgojIE1hbmFnZWQgc3BlY2llcyBieSBNaWQtQXRsYW50aWMgQ291bmNpbCBNYW5hZ2VtZW50IFBsYW5zLCBhbmQgU3RhdGUgd2F0ZXJzCiMgaHR0cHM6Ly93d3cuZmlzaGVyaWVzLm5vYWEuZ292L25ldy1lbmdsYW5kLW1pZC1hdGxhbnRpYy9jb21tZXJjaWFsLWZpc2hpbmcvbmV3LWVuZ2xhbmQtbWlkLWF0bGFudGljLWZpc2hlcnktbWFuYWdlbWVudC1wbGFucwoKU3BlY2llcyA8LSBjKAogICMgIlNjb21iZXIgc2NvbWJydXMiLAogICMgIkRvcnl0ZXV0aGlzIChBbWVyaWdvKSBwZWFsZWlpIiwgI2xvbmdmaW4gc3F1aWQgV0UgRE9OVCBIQVZFIElUCiAgIyAiUGVwcmlsdXMgdHJpYWNhbnRodXMiLCAjIGJ1dHRlcmZpc2gKICAjICJJbGxleCBpbGxlY2Vicm9zdXMiLCAjc2hvcnRmaW4gc3F1aWQKICAiUGFyYWxpY2h0aHlzIGRlbnRhdHVzIiwgI3N1bW1lciBmbG91bmRlcgogICJTdGVub3RvbXVzIGNocnlzb3BzIiwgI1NjdXAiCiAgIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIjLCAjIGJsYWNrIHNlYSBiYXNzCiAgIyAiUG9tYXRvbXVzIHNhbHRhdHJpeCIsICMgQmx1ZWZpc2gKICAjICJMb3Bob2xhdGlsdXMgY2hhbWFlbGVvbnRpY2VwcyIsICNnb2xkZW4gdGlsZWZpc2gKICAjICJDYXVsb2xhdGlsdXMgbWljcm9wcyIsICNibHVlbGluZSB0aWxlZmlzaAogICMgIkNsdXBlYSBoYXJlbmd1cyIgIyBBdGxhbnRpYyBoZXJyaW5nIChKb2ludGx5IGluIFN0YXRlIGFuZCBGZWRlcmFsIFdhdGVycykKICApCgoKc3BwX3BhdGhzIDwtIGxpc3QuZmlsZXMobXlfcGF0aCgiUiIsZXh0cmFfcGF0aCA9ICJQYXJ0aWFsL0ludGVycG9sYXRpb24iKSkKCiMgU29tZSBnaWJpcmlzIGZvciBuYW1lcwp0YXhvbl9saXN0IDwtIGdzdWIoIl8iLCIgIixzcHBfcGF0aHMpCnRheG9uX2xpc3QgPC0gZ3N1YigidGlmICIsIiIsdGF4b25fbGlzdCkKdGF4b25fbGlzdCA8LSBnc3ViKCIuY3N2IiwiIix0YXhvbl9saXN0KQoKdGF4b25fbGlzdCA8LSB0YXhvbl9saXN0W3RheG9uX2xpc3QgJWluJSBTcGVjaWVzXQoKIyBOb3cgc2V0IGEgbGlzdCBvZiBmaWxlcyB0byByZWFkCnRheG9uX3JlYWQgPC0gcGFzdGUwKCJ0aWZfIix0YXhvbl9saXN0LCIuY3N2IikKdGF4b25fcmVhZCA8LSBnc3ViKCIgIiwiXyIsdGF4b25fcmVhZCkKCnRheG9uX3JlYWQgPC0gc3BwX3BhdGhzW3NwcF9wYXRocyAlaW4lIHRheG9uX3JlYWRdCgp0YXhvbl9yZWFkIDwtIHBhc3RlMChteV9wYXRoKCJSIixleHRyYV9wYXRoID0gIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIpLHRheG9uX3JlYWQpCgoKIyBMb2FkIGFsbCBzcCBpbiBvbmUgdGFibGUKaGlzdG9yaWNfc3BwIDwtIGJpbmRfcm93cyhsYXBwbHkodGF4b25fcmVhZCwgZnJlYWQpKSAlPiUgCiAgbXV0YXRlKHN0YXRlID0gc3RyX3RvX3NlbnRlbmNlKHN0YXRlKSkKCgp1bmlxdWUoaGlzdG9yaWNfc3BwJHNwcCkKCiMgU3BhdGlhbCBkYXRhClN0YXRlcyA8LSBjKCJtYWluZSIsICJuZXcgaGFtcHNoaXJlIiwgIm1hc3NhY2h1c2V0dHMiLCAiY29ubmVjdGljdXQiLCAicmhvZGUgaXNsYW5kIiwgIm5ldyB5b3JrIiwgIm5ldyBqZXJzZXkiLCAiZGVsYXdhcmUiLCAibWFyeWxhbmQiLCAidmlyZ2luaWEiLCAibm9ydGggY2Fyb2xpbmEiKSAKCiMgVVMgU3RhdGUgTWFwIChsYW5kKQpsYW5kX3NmIDwtIHN0X2FzX3NmKG1hcCgic3RhdGUiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSkgJT4lIAogIGZpbHRlcihJRCAlaW4lIFN0YXRlcykgJT4lIAogIG11dGF0ZShhYnJldiA9IGMoIkNPIiwiREUiLCJNRSIsIk1EIiwiTUEiLCJOSCIsIk5KIiwiTlkiLCJOQyIsIlJJIiwiVkkiKSwKICAgICAgICAgc3RhdGUgPSBzdHJfdG9fc2VudGVuY2UoSUQpCiAgICAgICAgICkKCiMgUGVyaW9kcwpwZXJpb2RzIDwtdGliYmxlKAogIG9yZGVyID0gYyhyZXAoImEiLDEyKSwKICAgICAgICAgICAgcmVwKCJiIiwxMiksCiAgICAgICAgICAgIHJlcCgiYyIsMTIpLAogICAgICAgICAgICByZXAoImQiLDExKQogICksCiAgbGFiZWwgPSBjKHJlcCgiMTk3My0xOTg0IiwxMiksCiAgICAgICAgICAgIHJlcCgiMTk4NS0xOTk2IiwxMiksCiAgICAgICAgICAgIHJlcCgiMTk5Ny0yMDA4IiwxMiksCiAgICAgICAgICAgIHJlcCgiMjAwOS0yMDE5IiwxMSkKICApLAogIHllYXIgPSBjKHNlcSgxOTczLDE5ODQsMSksCiAgICAgICAgICAgc2VxKDE5ODUsMTk5NiwxKSwKICAgICAgICAgICBzZXEoMTk5NywyMDA4LDEpLAogICAgICAgICAgIHNlcSgyMDA5LDIwMTksMSkKICApCikKCgpzdGF0ZV9sYXQgPC0gaGlzdG9yaWNfc3BwICU+JQogIGdyb3VwX2J5KHN0YXRlKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgb3JkZXIgPSBtZWFuKGxhdCkKICApICU+JSAKICBtdXRhdGUoYWJyZXYgPSBjKCJDVCIsIkRFIiwiTUUiLCJNRCIsIk1BIiwiTkgiLCJOSiIsIk5ZIiwiTkMiLCJSSSIsIlZBIikKICApICU+JSAKICBhcnJhbmdlKGRlc2Mob3JkZXIpKSAlPiUgCiAgbXV0YXRlKG9yZGVyPSBsZXR0ZXJzWzE6MTFdKQoKCgojIFN0YXRlIHBhbGxldAoKc3RhdGVfcGFsbGV0IDwtIGMod2VzX3BhbGV0dGUobiA9IDUsIG5hbWUgPSAiRGFyamVlbGluZzEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlc19wYWxldHRlKG4gPSA1LCBuYW1lID0gIkRhcmplZWxpbmcyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHdlc19wYWxldHRlKG4gPSAyLCBuYW1lID0gIkdyYW5kQnVkYXBlc3QxIikKICAgICAgICAgICAgICAgICAgIiNGRDY0NjciCiAgICAgICAgICAgICAgICAgICkKCgoKIyBwcmludCBmb3Igbm90ZWJvb2sKaGVhZChoaXN0b3JpY19zcHApCmBgYAoKIyMgQXZlcmFnZSBwcm9wb3J0aW9uCgpUaGlzIG1hcCBzaG93cyB0aGUgYWdncmVnYXRlZCBleHRyYXBvbGF0ZWQgdmFsdWUgZnJvbSBhbGwgdGhyZWUgc3BlY2llcyBwZXIgU3RhdGUgYXZlcmFnZSBhY3Jvc3MgdGhlIHdob2xlIHN0dWR5IHBlcmlvZCB3aXRoaW4gZWFjaCBTdGF0ZSdzIHdhdGVyLgoKKk5vdGU6KiBUaGlzIGlzIGludGVuZGVkIHRvIGJlIGEgc3VwcGxlbWVudGFsIGZpZ3VyZQoKYGBge3IgYXJlYV9tYXBfc3RhdGUsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEyfQoKIGRhdGFfZ3JpZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHN0YXRlLGxhdCxsb24scmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN1bSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAjIHN1bSBvZiBhbGwgc3BlY2llcwogIGdyb3VwX2J5KHN0YXRlLGxhdCxsb24scmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHN1bSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICMgYXZlcmFnZSBvZiBhbGwgeWVhcnMKCgpnZ3Bsb3QoZGF0YSA9IHN1YnNldChkYXRhX2dyaWQsICFpcy5uYShtZWFuKSkpICsKICBnZW9tX3RpbGUoCiAgICBhZXMoCiAgICAgIHggPSBsb24sCiAgICAgIHkgPSBsYXQsCiAgICAgIGZpbGwgPSBtZWFuLAogICAgICBjb2wgPSBtZWFuCiAgICApCiAgKSArCiAgZ2VvbV9zZihkYXRhID0gbGFuZF9zZiwgYWVzKCkpICsKICBmYWNldF93cmFwKH4gc3RhdGUgICsgIHJlZ2lvbiwKICAgICAgICAgICAgIG5jb2wgPSA0KSArCiAgbGFicyh4ID0gIkxvbmdpdHVkZSIsIHkgPSAiTGF0aXR1ZGUiKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKCJNZWFuIEludGVycG9sYXRpb24iLCBhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXMoIk1lYW4gSW50ZXJwb2xhdGlvbiIsIGFscGhhID0gMC44KSArCiAgdGhlbWVfYncoKQpgYGAKCiMjIFByb3BvcnRpb24gQ2hhbmdlCgpIZXJlIHdlIHNob3cgdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiB0aGUgaW50ZXJwb2xhdGlvbiBieSBTdGF0ZSBhbmQgdGltZSBwZXJpb2QuIFRpbWUgcGVyaW9kcyB3ZXJlIGFyYml0cmFyeSBkZWZpbmVkIGFzOwoKLSBFYXJseTsgMTk3MyB0byAxOTg0Ci0gTWlkOyAxOTg1IHRvIDE5OTcKLSBMYXRlOyAxOTk4IHRvIDIwMTEKLSBOb3c7IDIwMTIgdG8gMjAxOQoKKk5vdGVzOiogRmlndXJlIHJlcHJlc2VudHMgdGhlICoqU3ByaW5nKiogc3VydmV5LiBUaGlzIGNvbXB1dGF0aW9uIGNvbnNpZGVycyB0aGUgT3ZlcmxhcHBpbmcgb2Ygc3RhdGUgd2F0ZXJzLgoKIyMjIER5bmFtaWMgZmlndXJlOiBBZ2dyZWdhdGVkIFByb3BvcnRpb25hbCBjaGFuZ2UgcGVyIHN1cnZleQoKYGBge3IgYXJlYV9tYXBfYWdncmVnYXRlZCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodD02fQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKCnN0YXRlX2ZpdCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgbGVmdF9qb2luKHBlcmlvZHMsCiAgICAgICAgICAgIGJ5ID0gInllYXIiKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUsb3JkZXIsbGFiZWwscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fcGVyID0gcm91bmQobWVhbihwZXJjZW50YWdlKSksLmdyb3VwcyA9ICJkcm9wIikKCiMgY2hlY2sgcGVyY2VudGFnZXMKIyBzdGF0ZV9maXQgJT4lIAojICAgZ3JvdXBfYnkocGVyaW9kKSAlPiUgCiMgICBzdW1tYXJpc2Uoc3VtKG1lYW5fcGVyKSkKCgpwIDwtIGxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gInN0YXRlIikgJT4lIAogIGdncGxvdCgpICsKICAjIGdlb21fc2YoYWVzKGZpbGwgPSBtZWFuX3BlcikpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIsIHRleHQgPSBwYXN0ZShzdGF0ZSwgbWVhbl9wZXIsIiUgb2YgcHJvcG9ydGlvbiIpKSkgKwogIHZpcmlkaXM6OnNjYWxlX2ZpbGxfdmlyaWRpcygiQXZlcmFnZSBwcm9wb3J0aW9uIHBlciBTdGF0ZSIsIGFscGhhID0gMC44KSArCiAgZmFjZXRfd3JhcCh+IHJlZ2lvbiArIGxhYmVsLCAKICAgICAgICAgICAgIG5yb3cgPSAyKSArCiAgbGFicyh4ID0gIkxhdGl0dWRlIiwgCiAgICAgICB5ID0gIkxvbmdpdHVkZSIpICsKICBteV9nZ3RoZW1lX3AoZmFjZXRfdHhfcyA9IDEyLAogICAgICAgICAgICAgICBsZWdfcG9zID0gImJvdHRvbSIpICsKICB0aGVtZShsZWdlbmQua2V5LndpZHRoID0gdW5pdCgxLCJsaW5lIikpICsKICB0aGVtZV9kYXJrKCkKCmdncGxvdGx5KHAsCiAgICAgICAgIHRvb2x0aXAgPSAidGV4dCIsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IEZBTFNFKSAlPiUgCiAgICBzdHlsZShob3ZlcmxhYmVsID0gbGlzdChiZ2NvbG9yID0gIndoaXRlIiksIGhvdmVyb24gPSAiZmlsbCIpCgoKYGBgCgoKIyMjIFBhcGVyIGZpZ3VyZTsgUGVyIHNwZWNpZXMgbWFwcwoKYGBge3IgcGFwZXJfZmlndXJlX2FyZWFfbWFwLCBldmFsID0gRiwgZWNobyA9IFQsIHJlc3VsdHM9J2hpZGUnfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbixzcHApICU+JSAKICBzdW1tYXJpc2UodG90YWxfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09VCksLmdyb3VwcyA9ICJkcm9wIikKCgpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbixzcHApICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iLCJzcHAiKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRhZ2UgPSBzdGF0ZV92YWx1ZS90b3RhbF92YWx1ZSoxMDApICU+JSAKICBsZWZ0X2pvaW4ocGVyaW9kcywKICAgICAgICAgICAgYnkgPSAieWVhciIpICU+JSAKICBncm91cF9ieShzdGF0ZSxvcmRlcixsYWJlbCxyZWdpb24sc3BwKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fcGVyID0gcm91bmQobWVhbihwZXJjZW50YWdlKSksLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogICNPbmx5IHNob3cgcmVzdWx0cyBmb3Igc3ByaW5nCiAgZmlsdGVyKHN0cl9kZXRlY3QocmVnaW9uLCJTcHJpbmciKSkgJT4lIAogIG11dGF0ZShzcHAgPSBnc3ViKCIgIiwiXG4iLHNwcCkpCgojIFRoZSBwbG90Cm1hcF9wbG90IDwtIGxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gInN0YXRlIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIpKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKCJBdmVyYWdlIHByb3BvcnRpb24gcGVyIFN0YXRlIiwgYWxwaGEgPSAwLjgpICsKICBmYWNldF9ncmlkKHNwcCB+IGxhYmVsKSArCiAgbGFicyh4ID0gIkxvbmdpdHVkZSIsIAogICAgICAgeSA9ICJMYXRpdHVkZSIpICsKICBteV9nZ3RoZW1lX3AoZmFjZXRfdHhfcyA9IDIwLAogICAgICAgICAgICAgICBsZWdfcG9zID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgIGF4eF90eF9hbmcgPSA0NSwKICAgICAgICAgICAgICAgYXhfdHhfcyA9IDEyLAogICAgICAgICAgICAgICBheF90bF9zID0gMTgsCiAgICAgICAgICAgICAgIGhqdXN0ID0gMSkgKwogIHRoZW1lKGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDQsImxpbmUiKSkgCgoKICBnZ3NhdmUoZmlsZW5hbWUgPSAicHJvcG9ydGlvbl9jaGdfc3BwLmpwZyIsCiAgICAgICAgIHBsb3QgPSBtYXBfcGxvdCwKICAgICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICAgIHdpZHRoID0gMTQsCiAgICAgICAgIGhlaWdodCA9IDE0CiAgICAgICAgICkKCgpgYGAKCgohW1Byb3BvcnRpb24gY2hhbmdlIHBlciBzcGVjaWVzIG1hcCBmb3IgcGFwZXJdKC9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL1Jlc3VsdHMvRmlndXJlcy9wcm9wb3J0aW9uX2NoZ19zcHAuanBnKQoKCiMjIyBQYXBlciBmaWd1cmU6IEFnZ3JlZ2F0ZWQgUHJvcG9ydGlvbmFsIGNoYW5nZQoKYGBge3IgYXJlYV9tYXBfYWdncmVnYXRlZF9mb3JtYW5zLCBldmFsID0gVCwgZWNobyA9IFQsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0PTZ9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgoKc3RhdGVfZml0IDwtIGhpc3RvcmljX3NwcCAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24pICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRhZ2UgPSBzdGF0ZV92YWx1ZS90b3RhbF92YWx1ZSoxMDApICU+JSAKICBsZWZ0X2pvaW4ocGVyaW9kcywKICAgICAgICAgICAgYnkgPSAieWVhciIpICU+JSAKICBncm91cF9ieShzdGF0ZSxvcmRlcixsYWJlbCxyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobWVhbl9wZXIgPSByb3VuZChtZWFuKHBlcmNlbnRhZ2UpKSwuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgZmlsdGVyKHN0cl9kZXRlY3QocmVnaW9uLCJTcHJpbmciKSkKCgphZ2dfbWFwIDwtIGxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gInN0YXRlIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIpKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKCJBdmVyYWdlIHByb3BvcnRpb24gcGVyIFN0YXRlIiwgYWxwaGEgPSAwLjgpICsKICBmYWNldF93cmFwKH4gbGFiZWwsIG5yb3cgPSAxKSArCiAgbGFicyh4ID0gIkxvbmdpdHVkZSIsIAogICAgICAgeSA9ICJMYXRpdHVkZSIpICsKICBteV9nZ3RoZW1lX3AoZmFjZXRfdHhfcyA9IDE2LAogICAgICAgICAgICAgICBsZWdfcG9zID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgIGxlZ190bF9zID0gMTQsCiAgICAgICAgICAgICAgIGF4X3R4X3MgPSAxMCwKICAgICAgICAgICAgICAgYXhfdGxfcyA9IDE0KSArCiAgdGhlbWUobGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMiwibGluZSIpKSAKCiAgZ2dzYXZlKGZpbGVuYW1lID0gInByb3BvcnRpb25fY2hnX2FnZy5qcGciLAogICAgICAgICBwbG90ID0gYWdnX21hcCwKICAgICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICAgIHdpZHRoID0gOSwKICAgICAgICAgaGVpZ2h0ID0gNQogICAgICAgICApCgpgYGAKCiFbUHJvcG9ydGlvbiBjaGFuZ2UgYWdncmVnYXRlZCBhbGwgc3BlY2llcyBtYXAgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvcHJvcG9ydGlvbl9jaGdfYWdnLmpwZykKCgojIyBBcmVhIHBsb3QKClRoaXMgZ3JhcGggc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgdGhlIGludGVycG9sYXRpb24gdmFsdWUgZWFjaCBTdGF0ZSBoYXMgb3ZlciB0aW1lLgoKKk5vdGU6KiBUaGlzIHBsb3QgaXMgaW50ZXJhY3RpdmUuIEZvciBlYXNlIGNvbXBhcmlzb24gYmV0d2VlbiBTdGF0ZXMgeW91IGNhbjsKCi0gKk9uZSogY2xpY2sgb24gYW55IFN0YXRlIHRvICpyZW1vdmUqIGl0IGZyb20gdGhlIHBsb3QgCi0gKlR3byogY2xpY2tzIG9uIGFueSBTdGF0ZSB0byAqaXNvbGF0ZSBpdCogZnJvbSB0aGUgcGxvdCAob3RoZXIgc3RhdGVzIGNhbiB0aGVuIGJlIGFkZGVkIGJ5IGp1c3QgY2xpY2tpbmcgb24gdGhlbSkuCi0gVGhlIGJvdHRvbSBwYW5lbCBhbGxvd3MgeW91IHRvIHJlZHVjZSB0aGUgdGltZSBmcmFtZQoKIyMjIER5bmFtaWMgYWdncmVnYXRlZCBwbG90CgpgYGB7ciBkeW5hbWljX2FyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkKCiMgUGxvdCBtZQpwIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQocGVyY2VudGFnZSksCiAgICAgIGZpbGwgPSBzdGF0ZQogICAgKQogICkgKwogIHlsYWIoIlBlcmNlbnRhZ2UgKCUpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpICsKICB0aGVtZV9kYXJrKCkKCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUKICByYW5nZXNsaWRlcigpCgpgYGAKCiMjIEFyZWEgcGxvdCAocnVubmluZyBtZWFuKQoKVGhpcyBncmFwaCBzaG93cyB0aGUgcHJvcG9ydGlvbiBvZiBlYWNoIFN0YXRlIHNtb290aGVkIG92ZXIgYSAqMTAgeWVhcnMgcnVubmluZyBtZWFuKiouIEl0IGFsbG93cyB0byBiZXR0ZXIgc2VlIGluY3JlYXNpbmcgYW5kIGRlY3JlYXNpbmcgdHJlbmRzLgoKIyMjIER5bmFtaWMgYWdncmVnYXRlZCBwbG90CgoqTm90ZToqIFRoaXMgcGxvdCBpcyBhbHNvIGludGVyYWN0aXZlIGFuZCB0aHVzLCBmb2xsb3dzIHRoZSBzYW1lIG9wdGlvbnMgb2YgdGhlIHByZXZpb3VzIG9uZS4KCmBgYHtyIGFyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbiwuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUscmVnaW9uKSAlPiUgCiAgbXV0YXRlKFJNZWFuID0gem9vOjpyb2xsbWVhbih4ID0gcGVyY2VudGFnZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtPVQpCiAgICApICU+JSAgCiAgbGVmdF9qb2luKHN0YXRlX2xhdCkKCiMgUGxvdCBtZQpwIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQoUk1lYW4pLAogICAgICBmaWxsID0gc3RhdGUKICAgICAgIyBmaWxsID0gb3JkZXIKICAgICkKICApICsKICB5bGFiKCIxMCB5cnMgcnVubmluZyBhdmVyYWdlICglKSIpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgICJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICAjIGxhYmVscyA9IHN0YXRlX2ZpdCAlPiUgYXJyYW5nZShvcmRlcikgJT4lICBwdWxsKHN0YXRlKSAlPiUgdW5pcXVlKCkKICApICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpICsKICB0aGVtZV9kYXJrKCkKCnN1cHByZXNzV2FybmluZ3MoCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUgCiAgIyBhZGRfdHJhY2UoKSAlPiUgCiAgcmFuZ2VzbGlkZXIoKQopCgpgYGAKCiMjIyBQYXBlciBmaWd1cmU6IEFnZ3JlZ2F0ZWQgUHJvcG9ydGlvbmFsIGNoYW5nZQoKYGBge3IgcGxvdF9hcmVhX2F2ZV9hZ2csIGV2YWwgPSBGLCBlY2hvID0gRiwgcmVzdWx0cz0naGlkZSd9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHJlZ2lvbikgJT4lIAogIG11dGF0ZShSTWVhbiA9IHpvbzo6cm9sbG1lYW4oeCA9IHBlcmNlbnRhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKSAlPiUgCiAgI09ubHkgc2hvdyByZXN1bHRzIGZvciBzcHJpbmcKICBmaWx0ZXIoc3RyX2RldGVjdChyZWdpb24sIlNwcmluZyIpLAogICAgICAgICAhaXMubmEoUk1lYW4pICMgUmVtb3ZlIE5BcyBmcm9tIHJvbGxtZWFuCiAgICAgICAgICkgJT4lICAKICBsZWZ0X2pvaW4oc3RhdGVfbGF0KQoKIyBQbG90IG1lCmFnZ19hcmVhIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQoUk1lYW4pLAogICAgICBmaWxsID0gb3JkZXIKICAgICAgIyBmaWxsID0gc3RhdGUKICAgICkKICApICsKICB5bGFiKCJQcm9wb3Rpb24gKDEwIHlycyBydW5uaW5nIGF2ZXJhZ2UpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgICJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICBsYWJlbHMgPSBzdGF0ZV9maXQgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgKSArCiAgbXlfZ2d0aGVtZV9wKGxlZ19wb3MgPSAicmlnaHQiKSArCiAgdGhlbWUobGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMSwibGluZSIpKQoKCiAgZ2dzYXZlKGZpbGVuYW1lID0gImFyZWFfcGxvdF9hdmdfYWdnLmpwZyIsCiAgICAgICAgIHBsb3QgPSBhZ2dfYXJlYSwKICAgICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICAgIHdpZHRoID0gOCwKICAgICAgICAgaGVpZ2h0ID0gNgogICkKCgpgYGAKCiFbUHJvcG9ydGlvbiBjaGFuZ2UgYWdncmVnYXRlZCBhbGwgc3BlY2llcyBtYXAgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvYXJlYV9wbG90X2F2Z19hZ2cuanBnKQoKIyMjIFBhcGVyIGZpZ3VyZTogUGVyIFNwZWNpZXMgUHJvcG9ydGlvbmFsIGNoYW5nZQoKYGBge3IgcGFwZXJfcGxvdF9hcmVhX2F2ZV9zcHAsIGV2YWwgPSBGLCBlY2hvID0gRiwgcmVzdWx0cz0naGlkZSd9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uLHNwcCkgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKCiMgZ3JvdXAgYnkgc3RhdGUKc3RhdGVfZml0IDwtIGhpc3RvcmljX3NwcCAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24sc3BwKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIiwic3BwIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUscmVnaW9uLHNwcCkgJT4lIAogIG11dGF0ZShSTWVhbiA9IHpvbzo6cm9sbG1lYW4oeCA9IHBlcmNlbnRhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKSAlPiUgCiAgI09ubHkgc2hvdyByZXN1bHRzIGZvciBzcHJpbmcKICBmaWx0ZXIoc3RyX2RldGVjdChyZWdpb24sIlNwcmluZyIpLAogICAgICAgICAhaXMubmEoUk1lYW4pICMgUmVtb3ZlIE5BcyBmcm9tIHJvbGxtZWFuCiAgICAgICAgICkgJT4lICAKICBsZWZ0X2pvaW4oc3RhdGVfbGF0KQoKIyBQbG90IG1lCnNzcF9hcmVhIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQoUk1lYW4pLAogICAgICBmaWxsID0gb3JkZXIKICAgICAgIyBmaWxsID0gc3RhdGUKICAgICkKICApICsKICB5bGFiKCJQcm9wb3Rpb24gKDEwIHlycyBydW5uaW5nIGF2ZXJhZ2UpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgICJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICBsYWJlbHMgPSBzdGF0ZV9maXQgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgKSArCiAgbXlfZ2d0aGVtZV9wKGxlZ19wb3MgPSAiYm90dG9tIikgKwogIHRoZW1lKGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDEsImxpbmUiKSkgKyAKICBmYWNldF93cmFwKH5zcHAsIG5jb2wgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIpCgoKICBnZ3NhdmUoZmlsZW5hbWUgPSAiYXJlYV9wbG90X2F2Z19zcHAuanBnIiwKICAgICAgICAgcGxvdCA9IHNzcF9hcmVhLAogICAgICAgICBwYXRoID0gbXlfcGF0aCgiUiIsIkZpZ3VyZXMiKSwKICAgICAgICAgd2lkdGggPSAxMCwKICAgICAgICAgaGVpZ2h0ID0gMTIKICApCgoKYGBgCiFbUHJvcG9ydGlvbiBjaGFuZ2UgYWdncmVnYXRlZCBhbGwgc3BlY2llcyBtYXAgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvYXJlYV9wbG90X2F2Z19zcHAuanBnKQoKIyMgSGlzdG9yaWMgcXVvdGEgVnMgZGlzdHJpYnV0aW9ucwoKVGhpcyBzZWN0aW9uIG9mIHRoZSByZXN1bHRzIGV4cGxvcmVzIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBoaXN0b3JpYyBkaXN0cmlidXRpb24gb2YgdGUgc3RvY2sgYW5kIHRoZSBoaXN0b3JpYyBxdW90YSBhbGxvY2F0aW9uLiBXZSBjb2xsZWN0ZWQgdGhlIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIHF1b3RhIHRoYXQgZWFjaCBTdGF0ZSBnZXRzIGZvciBlYWNoIHNwZWNpZXMuCgpSaWdodCBub3cgdGhlIGFuYWx5c2lzIG9ubHkgY292ZXJzIGJsYWNrIHNlYSBiYXNzLCBzdW1tZXIgZmxvdW5kZXIgYW5kIHNjdXAuIEJ1dCB3ZSBjYW4gZ28gc3BlY2VpcyBieSBzcGVjaWVzIHRvIHNlZSB3aGljaCBvbmVzIGhhdmUgdGhlaXIgcXVvdGEgYWxsb2NhdGVkIGJ5IHN0YXRlIHRvIGluY2x1ZGUgdGhlbSBpbiB0aGUgYW5hbHlzaXMuCgotIFtCbGFjayBTZWEgQmFzczsgKkNlbnRyb3ByaXN0aXMgc3RyaWF0YSpdKGh0dHBzOi8vd3d3Lm1hZm1jLm9yZy9uZXdzZmVlZC8yMDIxL2FzbWZjLWFuZC1tYWZtYy1hcHByb3ZlLWJzYi1jb21tZXJjaWFsLWFsbG9jYXRpb24tY2hhbmdlcykKCioqTm90ZToqKiBXZSBhcmUgdXNpbmcgdGhlIG5ldyBhbGxvY2F0aW9ucyBiYXNlZCBvbiB0aGUgc3RvY2sncyBtb3N0IHJlY2VudCBiaW9tYXNzIGRpc3RyaWJ1dGlvbiogCgotIFtTdW1tZXIgZmxvdW5kZXJdKGh0dHA6Ly93d3cuYXNtZmMub3JnL3VwbG9hZHMvZmlsZS81ZjlhZjgyYTIwMTlTdW1tZXJGbG91bmRlckZNUF9SZXZpZXcucGRmKQoKLSBbU2N1cF0oaHR0cDovL3d3dy5hc21mYy5vcmcvdXBsb2Fkcy9maWxlLzVmOTlkMDExMjAxOV9TY3VwX0ZNUF9SZXZpZXdfYXBwcm92ZWQucGRmKSBTdW1tZXIgcGVyaW9kCgpGb3IgU3RhdGUtbGV2ZWwgbWFuYWdlZCBzcGVjaWVzIHNlZSB0aGUgW0F0bGFudGljIFN0YXRlcyBNYXJpbmUgRmlzaGVyaWVzIENvbWlzc2lvbl0oaHR0cDovL3d3dy5hc21mYy5vcmcvZmlzaGVyaWVzLW1hbmFnZW1lbnQvcHJvZ3JhbS1vdmVydmlldykgd2Vic2l0ZSBhbmQgZ28gc3BlY2llcy1ieS1zcGVjaWVzLgoKCmBgYHtyIHN0YXRlX3F1b3RhX3RibCxldmFsPSBULCBlY2hvID0gVH0KCnF1b3RhX2FsbG9jYXRpb24gPC0gc3RhdGVfbGF0ICU+JSAKICBtdXRhdGUoCiAgICAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiA9IGMoCiAgICAgIDAuMDA0MCwgI01FCiAgICAgIDAuMDA0MCwgI05ICiAgICAgIDAuMTU2NCwgI01BCiAgICAgIDAuMTMyMywgI1JJCiAgICAgIDAuMDM2NywgI0NUCiAgICAgIDAuMDg1NywgI05ZCiAgICAgIDAuMjAxMCwgI05KCiAgICAgIDAuMDQxMSwgI0RFCiAgICAgIDAuMDg4OCwgI01ECiAgICAgIDAuMTYxNCwgI1ZBCiAgICAgIDAuMDg4OCAjTkMKICAgICksCiAgICAiUGFyYWxpY2h0aHlzIGRlbnRhdHVzIiA9IGMoCiAgICAgIDAuMDAwNDc1NiwgI01FIAogICAgICAwLjAwMDAwNDYsICNOSCAKICAgICAgMC4wNjgyMDQ2LCAjTUEgCiAgICAgIDAuMTU2ODI5OCwgI1JJIAogICAgICAwLjAyMjU3MDgsICNDVCAKICAgICAgMC4wNzY0Njk5LCAjTlkgCiAgICAgIDAuMTY3MjQ5OSwgI05KIAogICAgICAwLjAwMDE3NzksICNERSAKICAgICAgMC4wMjAzOTEwLCAjTUQKICAgICAgMC4yMTMxNjc2LCAjVkEKICAgICAgMC4yNzQ0NTg0ICNOQwogICAgKSwKICAgICJTdGVub3RvbXVzIGNocnlzb3BzIiA9IGMoCiAgICAgIDAuMDAxMjEwMSwgI01FCiAgICAgIDAuMDAwMDAwMCwgI0hOCiAgICAgIDAuMjE1ODcyOSwgI01BCiAgICAgIDAuNTYxOTQ1NiwgI1JJCiAgICAgIDAuMDMxNTM5OSwgI0NUCiAgICAgIDAuMTU4MjQ2NiwgI05ZCiAgICAgIDAuMDI5MTY2NywgI05KCiAgICAgIDAuMDAwMDAwMCwgI0RFCiAgICAgIDAuMDAwMTE5MCwgI01ECiAgICAgIDAuMDAxNjUwMiwgI1ZBCiAgICAgIDAuMDAwMjQ5MCAjTkMKICAgICkKICApICU+JSAKICBnYXRoZXIoInNwcCIsInF1b3RhIiw0OjYpCgojIERvdWJsZSBjaGVjayB0aGV5IGFsbCBhZGQgdG8gMS4uLgpxdW90YV9hbGxvY2F0aW9uICU+JSAKICBncm91cF9ieShzcHApICU+JSAKICBzdW1tYXJpc2VfYXQodmFycyhxdW90YSksc3VtKQoKCnF1b3RhX2FsbG9jYXRpb24gJT4lIAogIGFycmFuZ2Uob3JkZXIpICU+JSAKICBzZWxlY3QoLW9yZGVyKSAlPiUgCiAgc3ByZWFkKHNwcCxxdW90YSkgJT4lIAogIGthYmxlKCkKYGBgCgoKIyMjIEdldCBkYXRhIHJlYWR5CgpgYGB7cn0KCnRvdGFsX2ZpdGVkIDwtIGhpc3RvcmljX3NwcCAlPiUgCiAgZ3JvdXBfYnkoeWVhcixyZWdpb24sc3BwKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgojIGdyb3VwIGJ5IHN0YXRlCnN0YXRlX2ZpdCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHllYXIscmVnaW9uLHNwcCkgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIsInNwcCIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogICNPbmx5IHNob3cgcmVzdWx0cyBmb3Igc3ByaW5nCiAgZmlsdGVyKHN0cl9kZXRlY3QocmVnaW9uLCJTcHJpbmciKSkKCnF1b3RhX2RmIDwtIHF1b3RhX2FsbG9jYXRpb24gJT4lIAogIGxlZnRfam9pbihoaXN0b3JpY19zcHApICU+JSAKICBncm91cF9ieShzdGF0ZSxhYnJldix5ZWFyLHJlZ2lvbixzcHAscXVvdGEpICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iLCJzcHAiKSkgJT4lCiAgbXV0YXRlKERpc3RyaWJ1dGlvbiA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCwKICAgICAgICAgSGlzdG9yaWMgPSBxdW90YSoxMDApICU+JSAKICBncm91cF9ieShzdGF0ZSxxdW90YSxzcHApICU+JSAKICBtdXRhdGUoUk1lYW4gPSB6b286OnJvbGxtZWFuKHggPSBEaXN0cmlidXRpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKSAlPiUgCiAgI09ubHkgc2hvdyByZXN1bHRzIGZvciBzcHJpbmcKICBmaWx0ZXIoc3RyX2RldGVjdChyZWdpb24sIlNwcmluZyIpLAogICAgICAgICAhaXMubmEoUk1lYW4pICMgUmVtb3ZlIE5BcyBmcm9tIHJvbGxtZWFuCiAgICAgICAgICkgJT4lICAKICBsZWZ0X2pvaW4oc3RhdGVfbGF0KSAlPiUgCiAgZmlsdGVyKAogICAgIyBzcHAgPT0iQ2VudHJvcHJpc3RpcyBzdHJpYXRhIgogICAgc3BwICVpbiUgcXVvdGFfYWxsb2NhdGlvbiRzcHAKICApCgpoZWFkKHF1b3RhX2RmKSAlPiUgCiAga2FibGUoKQpgYGAKCiMjIyBFeHBsb3JpbmcgZGlmZmVyZW50IHdheXMgdG8gc2hvdyB0aGUgcmVzdWx0cwoKIyMjIyBEaWZmZXJlbmNlIGxpbmUgcGxvdAoKVGhpcyB2ZXJzaW9uIHNob3dzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIEhpc3RvcmljIHF1b3RhIGFsbG9jYXRpb24gYW5kIHRoZSBkaXN0cmlidXRpb24gcHJvcG9ydGlvbiBvZiB0aGUgc3RvY2s6CgotIGRpZmYgPCAwID0gdGhlIGRpc3RyaWJ1dGlvbiBwcm9wb3J0aW9uIGlzICpsYXJnZXIqIHRoYW4gdGhlIGFsbG9jYXRlZCBxdW90YQotIGRpZmYgPiAwID0gdGhlIGRpc3RyaWJ1dGlvbiBwcm9wb3J0aW9uIGlzICpzbWFsbGVyKiB0aGFuIHRoZSBhbGxvY2F0ZWQgcXVvdGEgCgpgYGB7cn0KIyBPcHRpb24gb25lCgpxdW90YV9kZiAlPiUKICBtdXRhdGUoZGlmZiA9IEhpc3RvcmljLSBEaXN0cmlidXRpb24sCiAgICAgICAgIGRpZmZfcm1lYW4gPSBSTWVhbi0gRGlzdHJpYnV0aW9uKSAlPiUgCiAgZ2F0aGVyKCJ0eXBlIiwidmFsdWUiLGRpZmY6ZGlmZl9ybWVhbikgJT4lIAogICMgVmlldygpCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSB2YWx1ZSwKICAgICAgY29sb3IgPSBvcmRlcgogICAgKQogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgiU3RhdGUiLAogICAgdmFsdWVzID0gc3RhdGVfcGFsbGV0LAogICAgbGFiZWxzID0gcXVvdGFfZGYgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgICApICsKICBmYWNldF9ncmlkKHR5cGV+c3BwLCAKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX2RhcmsoKQoKYGBgCiMjIyMgTGluZXR5cGUgcGxvdAoKSGVyZSwgd2UgcGxvdCB0aGUgZGlzdHJpYnV0aW9uYWwgcXVvdGEgKHNvbGlkIGxpbmVzKSB3aXRoIGVhY2ggU3RhdGUncyBhbGxvY2F0aW9uIHdpdGggZGFzaGVkICgtLS0tKSBsaW5lcwoKYGBge3J9CiMgT3B0aW9uIG9uZQoKcXVvdGFfZGYgJT4lIAogIGdhdGhlcigibGV2ZWwiLCJxdW90YSIsRGlzdHJpYnV0aW9uOlJNZWFuKSAlPiUgCiAgIyBtdXRhdGUoZGlmZiA9IHF1b3RhX3Blci0gcGVyY2VudGFnZSkgJT4lIAogICMgVmlldygpCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSBxdW90YSwKICAgICAgY29sb3IgPSBvcmRlcgogICAgKQogICkgKwogIGxhYnMoeCA9ICJZZWFyIix5ID0gIlF1b3RhICglKSIpICsKICBzY2FsZV9maWxsX21hbnVhbCgiU3RhdGUiLAogICAgdmFsdWVzID0gc3RhdGVfcGFsbGV0LAogICAgbGFiZWxzID0gcXVvdGFfZGYgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwoIlN0YXRlIiwKICAgIHZhbHVlcyA9IHN0YXRlX3BhbGxldCwKICAgIGxhYmVscyA9IHF1b3RhX2RmICU+JSBhcnJhbmdlKG9yZGVyKSAlPiUgIHB1bGwoc3RhdGUpICU+JSB1bmlxdWUoKQogICAgKSArCiAgc2NhbGVfbGluZXR5cGUoIlF1b3RhIikgKwogIGZhY2V0X2dyaWQoc3BwIH4gbGV2ZWwpKwogIHRoZW1lX2RhcmsoKQoKYGBgCiMjIyMgRWZmaWNpZW5jeSBpbmRleAoKVGhlIGlkZWEgaGVyZSBpcyBjcmVhdGUgYW5kICplZmZpY2llbmN5IGluZGV4KiAoRGFuZ2VyISkgdGhhdCBjb21wdXRlcyB0aGUgYWxpZ25tZW50IGJldHdlZW4gdGhlIGRpc3RyaWJ1dGlvbiBhbmQgdGhlIGFjdHVhbCBhbGxvY2F0aW9uLiBUaGUgaW5kZXggaXMgc2ltcGx5OwoKJCRlaSA9IFxmcmFje0hpc3RvcmljUXVvdGF9e0Rpc3RyaWJ1dGlvblByb3BvcnRpb259JCQgClNvLCBpbiBjYXNlcyB3aGVyZSAqZWkqID0gMSwgdGhlIHF1b3RhIGlzIGFsaWduZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uOyB3aGVuICplaSogPiAxIHRoZW4gdGhlIGhpc3RvcmljIHF1b3RhIGlzIG1vcmUgdGhhbiB0aGUgc3RvY2sncyBTdGF0ZSdzIGRpc3RyaWJ1dGlvbiwgY29udHJhcmlseSwgKmVpKiA8IDEgbWVhbnMgdGhhdCB0aGUgaGlzdG9yaWMgcXVvdGEgaXMgbGVzcyB0aGFuIHdoYXQgdGhlIFN0YXRlIGN1cnJlbnRseSBoYXMuCgoKKipOb3RlOioqIAotIFRoZXJlIGFyZSBzb21lIGNyYXp6eSBvdXRsaWVycyB0aGF0IGhhdmUgYmVlbiByZW1vdmVkLCBmb3Igbm93Li4uIAotIEJvdHRvbSBwbG90IHJlcHJlc2VudGluZyBpbmRleCBhcyBhIFJtZWFuCgojIyMjIyBBcyBhIG5vcm1hbCB5ZWFyIHRvIHllYXIKCmBgYHtyfQojIE9wdGlvbiBvbmUKCmVmZl9pbmRleCA8LSBxdW90YV9kZiAlPiUgCiAgIyBmaWx0ZXIoCiAgIyAgIHNwcCA9PSJDZW50cm9wcmlzdGlzIHN0cmlhdGEiCiAgIyApICU+JSAKICBtdXRhdGUoaW5kZXggPSBEaXN0cmlidXRpb24vSGlzdG9yaWMsCiAgICAgICAgIGluZGV4X3JtZWFuID0gUk1lYW4vSGlzdG9yaWMpICU+JQogIGdhdGhlcigibGV2ZWwiLCJpbmRleCIsaW5kZXg6aW5kZXhfcm1lYW4pICU+JQogIGZpbHRlcihpbmRleCA8IDUpICMgdGhlcmUgYXJlIHNvbWUgY3JhYWFhenkgb3V0bGllcnMKICAjIFZpZXcoKQogIApnZ3Bsb3QoZWZmX2luZGV4KSArCiAgZ2VvbV9saW5lKAogICAgYWVzKAogICAgICB4ID0geWVhciwKICAgICAgeSA9IGluZGV4LAogICAgICBjb2xvciA9IHN0YXRlCiAgICApLAogICkgKwogIGxhYnMoeCA9ICJZZWFyIix5ID0gIkVmZmljaWVuY3kgaW5kZXgiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoIlN0YXRlIiwKICAgIHZhbHVlcyA9IHN0YXRlX3BhbGxldCwKICAgIGxhYmVscyA9IHF1b3RhX2RmICU+JSBhcnJhbmdlKG9yZGVyKSAlPiUgIHB1bGwoc3RhdGUpICU+JSB1bmlxdWUoKQogICAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKCJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICBsYWJlbHMgPSBxdW90YV9kZiAlPiUgYXJyYW5nZShvcmRlcikgJT4lICBwdWxsKHN0YXRlKSAlPiUgdW5pcXVlKCkKICAgICkgKwogIGZhY2V0X2dyaWQobGV2ZWx+c3BwLAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWUiKSsKICB0aGVtZV9kYXJrKCkKCmBgYAo=